[comp.emacs] scope rules for "let"

narten@cs.purdue.EDU (Thomas Narten) (02/24/88)

I have buffer that is readonly for keystrokes, but is made writable by
functions operating on the buffer. I want the default to be readonly,
with explicit action required to make the buffer write only.

Based on other packages, I use the following trick:

1) the buffer is made readonly via (setq buffer-read-only "t")

2) whenever the buffer is to be modified, the following code is used:

(let (buffer-read-only)
     /* muck with the buffer */

     )

I want the buffer-read-only variable to be nil only during the
invocation of "let", reverting to its non-nil value upon exit. This is
apparently not taking place. I find that the buffer-read-only is being
left set to nil.

I conclude that "let" is not doing what I want. What I would like is
for let to push the variables onto the symbol table stack, and use
dynamic scope rules to have all subsequent references to the variables
with those name find the "recent" bindings. When "let" exits, I would
expect the temporary binding of those variables to pop off of the
stack and the previous meanings be restored.

Why does the above not work?

Do I really have to use setq to explicitly toggle the value of
buffer-read-only?

I am running gnu emacs 18.49.
-- 
Thomas Narten
narten@cs.purdue.edu or {ihnp4, allegra}!purdue!narten

narten@cs.purdue.EDU (Thomas Narten) (02/24/88)

In article  <3292@arthur.cs.purdue.edu> narten@cs.purdue.EDU (Thomas Narten) writes:
>(let (buffer-read-only)
>     /* muck with the buffer */
>
>     )
>

I found my problem. The code in "muck with the buffer" included a line
of the form:

(switch-to-buffer-other-window folder)

Switching buffers apparently prevents "buffer-read-only" from
reverting back to its original value upon exiting the "let". Moving
the line outside of the let fixed my problem.
-- 
Thomas Narten
narten@cs.purdue.edu or {ihnp4, allegra}!purdue!narten

lrs@esl.UUCP (Lynn Slater) (02/25/88)

Posting-Front-End: GNU Emacs 18.44.12 of Mon Nov 16 1987 on esl (berkeley-unix)


>I have buffer that is readonly for keystrokes, but is made writable by
>functions operating on the buffer. I want the default to be readonly,
>with explicit action required to make the buffer write only.

I have solved this in much the manner you suggest. Check that there is
not some other problem. For Example code follows:

(defun highlight-region (p1 p2)
  "Highlight the current region."
  (interactive "r")
  (let ((s (buffer-substring p1 p2))
	(inverse-video t)
	;; Do not change the modified flag
	(modified-flag  (buffer-modified-p))
	;; shadow the true local value of read-only
	(buffer-read-only nil)
	;; Prevent the generation of autosave files
	;; Don't you just love dynamic variable binding?
	(buffer-auto-save-file-name nil)
	;; we do not have to worry about backup files because
	;; they are not generated unless the buffer is saved.
	)
    (delete-region p1 p2)
    ;; force a redisplay, so that the screen image of the line "changes" later
    (if (fboundp 'update-display)
	(update-display)
      (sit-for 0))
    (insert s)
    (if (fboundp 'update-display)
	(update-display)
      (sit-for 0))
    (set-buffer-modified-p modified-flag)))

jbw@bucsb.UUCP (Joe Wells) (02/28/88)

In article <3292@arthur.cs.purdue.edu> narten@cs.purdue.EDU (Thomas Narten) writes:
>I have buffer that is readonly for keystrokes, but is made writable by
>functions operating on the buffer. I want the default to be readonly,
>with explicit action required to make the buffer write only.

>(let (buffer-read-only)
>     /* muck with the buffer */
>
>     )

Right in here is where the problem occurs.  If you use (set-buffer
...) inside of the "let", and you don't switch back to the original
buffer before exiting the "let", you get the error.

>I want the buffer-read-only variable to be nil only during the
>invocation of "let", reverting to its non-nil value upon exit. This is
>apparently not taking place. I find that the buffer-read-only is being
>left set to nil.

Actually the "t" value of buffer-read-only is being restored ... in a
different buffer!

>I conclude that "let" is not doing what I want. What I would like is
>for let to push the variables onto the symbol table stack, and use
>dynamic scope rules to have all subsequent references to the variables
>with those name find the "recent" bindings. When "let" exits, I would
>expect the temporary binding of those variables to pop off of the
>stack and the previous meanings be restored.
>
>Why does the above not work?

"buffer-read-only" is a buffer-local variable.  GNU Emacs does not
properly undo lambda bindings of buffer-local variables when you
switch buffers while in the context of the lambda binding.  You have
two options until this bug is fixed:

1) Don't use "let" to temporarily override the value of buffer-local
variables.

2)  Make sure you always exit a "let" with the same current buffer as
you entered it.

BTW, the GNU Emacs function "shrink-window-if-larger-than-buffer" in
electric.el makes this mistake.  I found out the hard way, when
buffer-file-name was being zapped, and I couldn't save my file ...

>Thomas Narten
>narten@cs.purdue.edu or {ihnp4, allegra}!purdue!narten

Joe Wells
jbw@bucsf.bu.edu