* Missing `with' macro? @ 2006-07-24 10:17 Mathias Dahl 2006-07-24 13:46 ` Stefan Monnier 2006-07-24 18:22 ` Richard Stallman 0 siblings, 2 replies; 18+ messages in thread From: Mathias Dahl @ 2006-07-24 10:17 UTC (permalink / raw) I am currently optimizing some defuns in tumme.el and found that I do the following repeatdely: (setq buf (find-file tumme-db-file)) ;; do a lot of stuff in it (save-buffer) ;; optionally (kill-buffer buf) I really like the different `with' macros that Emacs has and was surprised there wasn't any `with-file' macro, that could be callable like this: (with-file tumme-db-file ;; do stuff) It could have two modes, reading and writing as sometimes you just want to use the information in the opened file, not write back to it. I guess what I want is this, without the call to `insert-file-contents': (with-temp-file tumme-db-file (insert-file-contents tumme-db-file) ;; do stuff) What do others think? Is the with-temp-file + insert-file-contents combo enough? ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-07-24 10:17 Missing `with' macro? Mathias Dahl @ 2006-07-24 13:46 ` Stefan Monnier 2006-07-24 14:33 ` Mathias Dahl 2006-07-24 18:22 ` Richard Stallman 1 sibling, 1 reply; 18+ messages in thread From: Stefan Monnier @ 2006-07-24 13:46 UTC (permalink / raw) Cc: emacs-devel > (setq buf (find-file tumme-db-file)) > ;; do a lot of stuff in it > (save-buffer) ;; optionally > (kill-buffer buf) Just for the record, the above code will bomb out if the current window is a minibuffer or is dedicated: Always prefer find-file-noselect to find-file. Stefan "whose windows are all dedicated or minibuffers" PS: Regarding with-file, it would be nice, but please make sure it can be used also when you just want to read the file, and also when you specifically don't want the major mode to be set, and also when you do want the major mode to be set, and also be careful not to kill a pre-existing buffer inadvertently, ... ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-07-24 13:46 ` Stefan Monnier @ 2006-07-24 14:33 ` Mathias Dahl 0 siblings, 0 replies; 18+ messages in thread From: Mathias Dahl @ 2006-07-24 14:33 UTC (permalink / raw) Cc: emacs-devel > > (setq buf (find-file tumme-db-file)) > > ;; do a lot of stuff in it > > (save-buffer) ;; optionally > > (kill-buffer buf) > > Just for the record, the above code will bomb out if the current window is > a minibuffer or is dedicated: Always prefer find-file-noselect to find-file. Thanks for the advice! I will probably replace it with a combination of `with-temp-file' and `insert-file-contents'. > Stefan "whose windows are all dedicated or minibuffers" /Mathias - who has never cared about this dedicated business... :) ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-07-24 10:17 Missing `with' macro? Mathias Dahl 2006-07-24 13:46 ` Stefan Monnier @ 2006-07-24 18:22 ` Richard Stallman 2006-07-24 20:55 ` Jorgen Schaefer 2006-07-28 2:14 ` Stuart D. Herring 1 sibling, 2 replies; 18+ messages in thread From: Richard Stallman @ 2006-07-24 18:22 UTC (permalink / raw) Cc: emacs-devel I am currently optimizing some defuns in tumme.el and found that I do the following repeatdely: (setq buf (find-file tumme-db-file)) ;; do a lot of stuff in it (save-buffer) ;; optionally (kill-buffer buf) We don't usually call find-file for such temporary purposes. We usually use code like this: (with-temp-buffer (insert-file-contents file) operate on the file) except that if the file's already visited in a buffer, it is more efficient to use that buffer (and not kill it). To develop a general macro for this would be useful. It is not a trivial thing. Please start working on it if you want. The case of just examining a file without altering it, since that is more common, and easier. I suspect that we may need two totally different macros for the read-only case and the case of altering the file. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-07-24 18:22 ` Richard Stallman @ 2006-07-24 20:55 ` Jorgen Schaefer 2006-07-25 3:09 ` Richard Stallman 2006-07-28 2:14 ` Stuart D. Herring 1 sibling, 1 reply; 18+ messages in thread From: Jorgen Schaefer @ 2006-07-24 20:55 UTC (permalink / raw) Richard Stallman <rms@gnu.org> writes: > We don't usually call find-file for such temporary purposes. > We usually use code like this: > > (with-temp-buffer > (insert-file-contents file) > operate on the file) > > except that if the file's already visited in a buffer, > it is more efficient to use that buffer (and not kill it). > > To develop a general macro for this would be useful. It is not a > trivial thing. Please start working on it if you want. I have written such a macro for my program to generate my weblog and rss feed: (put 'with-file 'lisp-indent-function 1) (defmacro with-file (file &rest body) "Run BODY in a buffer visiting FILE. If the buffer was not open before calling this macro, it's killed afterwards." (let ((file-sym (make-symbol "file")) (existsp-sym (make-symbol "existsp")) (buf-sym (make-symbol "buf"))) `(let* ((,file-sym ,file) (,existsp-sym (get-file-buffer ,file-sym)) (,buf-sym (find-file-noselect ,file-sym))) (unwind-protect (with-current-buffer ,buf-sym (save-excursion (save-restriction (widen) ,@body))) (when (not ,existsp-sym) (kill-buffer ,buf-sym)))))) Regards, -- Jorgen -- ((email . "forcer@forcix.cx") (www . "http://www.forcix.cx/") (gpg . "1024D/028AF63C") (irc . "nick forcer on IRCnet")) ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-07-24 20:55 ` Jorgen Schaefer @ 2006-07-25 3:09 ` Richard Stallman 0 siblings, 0 replies; 18+ messages in thread From: Richard Stallman @ 2006-07-25 3:09 UTC (permalink / raw) Cc: emacs-devel (defmacro with-file (file &rest body) "Run BODY in a buffer visiting FILE. If the buffer was not open before calling this macro, it's killed afterwards." (let ((file-sym (make-symbol "file")) (existsp-sym (make-symbol "existsp")) (buf-sym (make-symbol "buf"))) `(let* ((,file-sym ,file) (,existsp-sym (get-file-buffer ,file-sym)) (,buf-sym (find-file-noselect ,file-sym))) Using find-file-noselect could be the right thing in some cases, but there are many cases (especially where you just read the file or scan it quickly) where that is much too heavy. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-07-24 18:22 ` Richard Stallman 2006-07-24 20:55 ` Jorgen Schaefer @ 2006-07-28 2:14 ` Stuart D. Herring 2006-07-28 2:23 ` Stuart D. Herring 2006-07-29 15:18 ` Richard Stallman 1 sibling, 2 replies; 18+ messages in thread From: Stuart D. Herring @ 2006-07-28 2:14 UTC (permalink / raw) Cc: emacs-devel, Mathias Dahl [-- Attachment #1: Type: text/plain, Size: 896 bytes --] > To develop a general macro for this would be useful. It is not a > trivial thing. Please start working on it if you want. The case of > just examining a file without altering it, since that is more common, > and easier. I suspect that we may need two totally different macros > for the read-only case and the case of altering the file. I've implemented a first draft of this, complete with file-writing capacity in the same macro: see the attached file and please comment. (In particular, is there a clean way to silence `save-buffer' or the equivalent?) I still don't quite have papers, but I am led to believe that it will happen Real Soon Now; since this isn't going into this release AFAIK, I hope that's not a problem. Davis -- This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping. [-- Attachment #2: with-file.el --] [-- Type: application/octet-stream, Size: 5120 bytes --] (put 'hide-message 'lisp-indent-function 0) (defmacro hide-message (&rest body) "Execute BODY, then restore the previous contents of the echo area. Messages produced by BODY are not logged." (let ((pm-sym (make-symbol "prev-msg"))) `(let ((,pm-sym (current-message)) message-log-max) ,@body (message ,pm-sym)))) (put 'with-file 'lisp-indent-function 4) (defmacro with-file (file visit reuse write &rest body) "Execute the forms in BODY in a buffer with FILE's text loaded. Point begins at the beginning of the buffer, which is not narrowed. The value returned is the value of the last form in BODY. VISIT t means actually visit the file, loading its appropriate major mode and local variables and such. VISIT nil means do none of these things; BODY will be executed in a buffer with the contents of FILE but that is visiting no file. Any other value for VISIT works like nil except that the file is read literally (see `insert-file-contents-literally'). REUSE non-nil means to use an existing buffer if it is visiting FILE. (The value of `find-file-existing-other-name' affects this determination.) The buffer will only be re-used if its literal status (see `find-file-literally') matches the literal status requested by VISIT. Note that reusing a buffer may mean that the text on which BODY operates differs from the actual contents of FILE. WRITE non-nil means to modify the file; if the BODY finishes normally, then the buffer is saved if the file was visited or written otherwise. If WRITE is neither t nor nil, saving messages are suppressed. The buffer will be read-only when BODY is executed iff WRITE is nil. If a buffer is created in the execution of this macro, it is killed when it finishes (even in the case of abnormal exit), regardless of any unsaved changes made." (let ((file-sym (make-symbol "file")) (visit-sym (make-symbol "visit")) (raw-sym (make-symbol "raw")) (reuse-sym (make-symbol "reuse")) (write-sym (make-symbol "write")) (quiet-sym (make-symbol "quiet")) (extant-sym (make-symbol "extant")) (extant-file-sym (make-symbol "extant-file")) (buf-sym (make-symbol "buf")) (reused-sym (make-symbol "reused")) (bro-sym (make-symbol "buf-readonly"))) `(let* ((,file-sym ,file) (,visit-sym ,visit) (,raw-sym (and ,visit-sym (not (eq ,visit-sym t)))) (,reuse-sym ,reuse) (,write-sym ,write) (,quiet-sym (and ,write-sym (not (eq ,write-sym t)))) (,extant-sym (if find-file-existing-other-name (find-buffer-visiting ,file-sym) (get-file-buffer ,file-sym))) (,extant-file-sym (and ,extant-sym (buffer-file-name ,extant-sym))) (,buf-sym (or (and ,reuse-sym ,extant-sym (eq (not (with-current-buffer ,extant-sym find-file-literally)) (not ,raw-sym)) ,extant-sym) (if (eq ,visit-sym t) (progn ;; We need to pretend that any other visiting buffer ;; doesn't actually exist. (if ,extant-sym (with-current-buffer ,extant-sym (setq buffer-file-name nil))) (find-file-noselect ,file-sym t)) (with-current-buffer (generate-new-buffer "*with-file*") (if (eq ,visit-sym nil) (insert-file-contents ,file-sym) (insert-file-contents-literally ,file-sym)) (current-buffer))))) (,reused-sym (eq ,buf-sym ,extant-sym)) (,bro-sym (with-current-buffer ,buf-sym buffer-read-only))) (with-current-buffer ,buf-sym (unwind-protect (save-excursion (save-restriction (widen) (goto-char (point-min)) ;; We don't just let-bind buffer-read-only because that ;; interacts poorly with switching buffers. (setq buffer-read-only (not ,write-sym)) (prog1 (save-current-buffer ,@body) (and (buffer-live-p ,buf-sym) ,write-sym (if (or ,reused-sym (eq ,visit-sym t)) (if ,quiet-sym (hide-message (save-buffer)) (save-buffer)) (let ((coding-system-for-write (if ,raw-sym 'no-conversion coding-system-for-write))) (widen) (write-region (point-min) (point-max) ,file-sym nil (if ,quiet-sym 'lambda)))))))) (when (buffer-live-p ,buf-sym) (setq buffer-read-only ,bro-sym) (unless ,reused-sym (set-buffer-modified-p nil) (kill-buffer nil))) (when (buffer-live-p ,extant-sym) (with-current-buffer ,extant-sym (setq buffer-file-name ,extant-file-sym)))))))) (defun with-file-test (file arg) "Test `with-file' by inserting at the beginning of FILE. Use 'silent with prefix ARG. Use 'raw with two C-u's." (interactive "f\nP") (with-file file (if (equal arg '(16)) 'raw t) nil (if arg 'silent t) (insert "foo\n") ;; Print some multibyte stuff to demonstrate the action of literal mode. (message "%S" (and (re-search-forward "[^\0-\d]" nil t) (match-string 0))))) [-- Attachment #3: Type: text/plain, Size: 142 bytes --] _______________________________________________ Emacs-devel mailing list Emacs-devel@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-devel ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-07-28 2:14 ` Stuart D. Herring @ 2006-07-28 2:23 ` Stuart D. Herring 2006-07-29 15:18 ` Richard Stallman 1 sibling, 0 replies; 18+ messages in thread From: Stuart D. Herring @ 2006-07-28 2:23 UTC (permalink / raw) Cc: emacs-devel, Mathias Dahl In my previous message I neglected to mention that I based my `with-file' macro on Jorgen Schaefer's; while I added a lot to it, I would be remiss to not acknowledge my starting point. Sorry-and-thanks, Jorgen. Davis -- This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-07-28 2:14 ` Stuart D. Herring 2006-07-28 2:23 ` Stuart D. Herring @ 2006-07-29 15:18 ` Richard Stallman 2006-08-01 1:06 ` Stuart D. Herring 1 sibling, 1 reply; 18+ messages in thread From: Richard Stallman @ 2006-07-29 15:18 UTC (permalink / raw) Cc: emacs-devel, mathias.dahl * This macro has two separate args REUSE and WRITE. But I think only two combinations make sense: t nil, and nil t. It is always wrong to reuse an existing buffer if you're going to modify the file. And if you're not going to modify it, there is never any point in not reusing one. So I think you should get rid of the REUSE argument. * This is a horrible kludge ;; We need to pretend that any other visiting buffer ;; doesn't actually exist. (if ,extant-sym (with-current-buffer ,extant-sym (setq buffer-file-name nil))) (find-file-noselect ,file-sym t)) and without an unwind-protect it will permanently ruin the other buffer if an error occurs. How about this instead? ;; Create a new buffer. (setq buf (create-file-buffer filename)) ;; find-file-noselect-1 may use a different buffer. (find-file-noselect-1 buf filename nowarn rawfile truename number)))))) * This seems like a mistake: ;; We don't just let-bind buffer-read-only because that ;; interacts poorly with switching buffers. (setq buffer-read-only (not ,write-sym)) What is the problem you're concerned about? * Use 'silent with prefix ARG. Use 'raw with two C-u's." Please write `silent' and `raw'; that is our convention. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-07-29 15:18 ` Richard Stallman @ 2006-08-01 1:06 ` Stuart D. Herring 2006-08-07 5:01 ` Richard Stallman 0 siblings, 1 reply; 18+ messages in thread From: Stuart D. Herring @ 2006-08-01 1:06 UTC (permalink / raw) Cc: emacs-devel > * This macro has two separate args REUSE and WRITE. > But I think only two combinations make sense: t nil, and nil t. > It is always wrong to reuse an existing buffer if you're going > to modify the file. And if you're not going to modify it, > there is never any point in not reusing one. If we use REUSE nil and WRITE t, then if the user has visited the file (which could easily be a file for which WRITE t makes sense, e.g. ~/.emacs.d/.whatever-package-rc) and has unsaved changes in it, those are effectively lost because they may clash with the updated file. Even if the user has not modified the buffer, the odd result is that the buffer is out of date as a result of actions within Emacs. Moreover, using REUSE nil can be useful if we want to read the actual file on disk and not whatever is in a buffer that is visiting the file (which could be a temporary modification, or an unstable version, or...). It also avoids any complications of file-local variables and so forth (so long as VISIT is nil or 'raw), or subsequent buffer-but-not-file effects (selective-display with ^M, user-added buffer-local variables, etc.). > * This is a horrible kludge > > ;; We need to pretend that any other visiting buffer > ;; doesn't actually exist. > (if ,extant-sym > (with-current-buffer ,extant-sym > (setq buffer-file-name nil))) > (find-file-noselect ,file-sym t)) > > and without an unwind-protect it will permanently ruin the other buffer > if an error occurs. How about this instead? I'll grant that it's a kludge, but I don't know of a better way (I respond to your suggestion below). There is in fact an unwind-protect on the majority of the code that will undo that effect; however, I realize now that it will not run if `find-file-noselect' exits abnormally. Failing a complete rewrite of this mechanism, I'll make sure that the kludge is protected more thoroughly. > ;; Create a new buffer. > (setq buf (create-file-buffer filename)) > ;; find-file-noselect-1 may use a different buffer. > (find-file-noselect-1 buf filename nowarn > rawfile truename number)))))) Three things: 1. Thanks for pointing me at `find-file-noselect-1'; I didn't realize it before, but it's exactly what I want here. I'll certainly use it. 2. Should we call `set-buffer-major-mode' here, like `find-file-noselect' does? 3. This does allow visiting a buffer repeatedly, but it doesn't entirely obviate the need for the kludge because the code that checks for a file being modified on disk since you read it when you try to edit it (my apologies that I don't know a name for this code) will notice another buffer visiting the file and will react if -its- modtime is out of date, even if the modtime of the edited buffer is recent. I discovered this while testing; I should have mentioned it in comments. Of course, I guess my kludge just reduces it to a race condition, where if the file is modified externally during the execution of `with-file' and another modification is made, the warning will appear anyway. Then again, is there anywhere in Emacs that we attempt to avoid that? Anyway, is there a better way to avoid the modtime problems? `find-file-noselect-1' solves everything else. > * This seems like a mistake: > > ;; We don't just let-bind buffer-read-only because that > ;; interacts poorly with switching buffers. > (setq buffer-read-only (not ,write-sym)) > > What is the problem you're concerned about? See (elisp)Intro to Buffer-Local; I was avoiding the problems discussed with the text "you can get Emacs very confused by binding the variable" near the bottom. I realize now, re-reading that, that a `save-excursion' (or even just `save-current-buffer', I guess) can prevent problems here... but what happens if the buffer is killed before exiting the `let'? A quick test on the 21.3 I have in front of me now seems to indicate that nothing bad happens, but I'd like some more assurance if I can get it. If it's true that nothing will get hurt then, I'll just let-bind `buffer-read-only' inside the `prog1' there and around the `save-current-buffer'. > * Use 'silent with prefix ARG. Use 'raw with two C-u's." > > Please write `silent' and `raw'; that is our convention. Sorry. It was a quick docstring for a testing function, written without thought, told by an idiot, full of sound and fury, signifying nothing. Davis -- This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-08-01 1:06 ` Stuart D. Herring @ 2006-08-07 5:01 ` Richard Stallman 2006-08-07 21:38 ` Stuart D. Herring 0 siblings, 1 reply; 18+ messages in thread From: Richard Stallman @ 2006-08-07 5:01 UTC (permalink / raw) Cc: emacs-devel If we use REUSE nil and WRITE t, then if the user has visited the file (which could easily be a file for which WRITE t makes sense, e.g. ~/.emacs.d/.whatever-package-rc) and has unsaved changes in it, those are effectively lost because they may clash with the updated file. Maybe that is correct. It would be as if some other unrelated program had altered the file. If the person tries to save his buffer, Emacs will report that the file has changed. To use the user's existing buffer would save the user's own unsaved changes without asking. That is completely unacceptable. I can see one other conceivable way to handle this case: to merge the changes that the program makes into the user's own buffer, imitating the example of CVS merging remote and local changes. But that is not easy to do. Unless we implement such merging, I stand by what I said: WRITE = t requires REUSE = nil. I don't follow this part: 3. This does allow visiting a buffer repeatedly, but it doesn't entirely obviate the need for the kludge because the code that checks for a file being modified on disk since you read it when you try to edit it (my apologies that I don't know a name for this code) I can't make sense of all those "it"s. will notice another buffer visiting the file and will react if -its- modtime is out of date, even if the modtime of the edited buffer is recent. I discovered this while testing; I should have mentioned it in comments. Please show me the code you're talking about; it is the only way I can understand this. See (elisp)Intro to Buffer-Local; I was avoiding the problems discussed with the text "you can get Emacs very confused by binding the variable" near the bottom. I realize now, re-reading that, that a `save-excursion' (or even just `save-current-buffer', I guess) can prevent problems here... but what happens if the buffer is killed before exiting the `let'? Nothing bad happens. Don't worry about this. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-08-07 5:01 ` Richard Stallman @ 2006-08-07 21:38 ` Stuart D. Herring 2006-08-08 18:01 ` Richard Stallman 2006-08-08 18:01 ` Richard Stallman 0 siblings, 2 replies; 18+ messages in thread From: Stuart D. Herring @ 2006-08-07 21:38 UTC (permalink / raw) Cc: emacs-devel > If we use REUSE nil and WRITE t, then if the user has visited the file > (which could easily be a file for which WRITE t makes sense, e.g. > ~/.emacs.d/.whatever-package-rc) and has unsaved changes in it, those > are > effectively lost because they may clash with the updated file. > > Maybe that is correct. It would be as if some other unrelated program > had altered the file. If the person tries to save his buffer, Emacs > will report that the file has changed. > > To use the user's existing buffer would save the user's own unsaved > changes without asking. That is completely unacceptable. Is it completely unacceptable even if the file in question is principally "owned" by code anyway? I can't imagine that `with-file' would ever be invoked on someone's source code unless it was a specialized tool that would (via confirmation or so) verify the user's intent. > I can see one other conceivable way to handle this case: to merge the > changes that the program makes into the user's own buffer, imitating > the example of CVS merging remote and local changes. But that is not > easy to do. I see other possibilities: 1. (and REUSE WRITE (buffer-modified-p #<buffer extant-buffer>) (error "Attempt to co-opt user's unsaved changes")) - that is, only allow REUSE and WRITE on an unmodified buffer. 2. Go on modifying (because of WRITE) the buffer (because of REUSE), but don't save the changes at the end, or else ask the user whether to save them. Either of these could be combined with a query beforehand: "Lisp wants to modify foobar.c. (S)ave your changes first or (r)evert the buffer first? (s or r)" (Of course, C-g would also be a useful response.) > Unless we implement such merging, I stand by what I said: > WRITE = t requires REUSE = nil. I'd really like to keep the option, but if we can't find a reasonable solution I'll do that. > Please show me the code you're talking about; it is the only way I can > understand this. OK, I've done my homework now. The querying function is `ask-user-about-supersession-threat'; it's called from lock_file() in filelock.c, which uses get_truename_buffer() to find the buffer whose modification time to examine. This means that if an existing buffer visiting the file is out of date, and get_truename_buffer() happens to return it instead of the up-to-date buffer created by `with-file', the supersession query will be raised. I don't know what the correct approach is here (without rewriting lock_file()): should I `flet' `ask-user-about-supersession-threat', or what? My current version of `with-file' does avoid losing the proper file name by destroying its filename only after entering the `unwind-protect' that restores it, and restoring it as the first unwind action. (This was made much simpler by the use of `find-file-noselect-1', as it reduced the period of time during which the file name needed to be hidden.) > Nothing bad happens. Don't worry about this. OK. Worrying halted (and `buffer-read-only' let-bound). Davis PS - While investigating this, I discovered the variable `buffer_count' in buffer.c: it seems to never be used by any code anywhere. Is it obsolete? -- This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-08-07 21:38 ` Stuart D. Herring @ 2006-08-08 18:01 ` Richard Stallman 2006-08-08 18:32 ` Stuart D. Herring 2006-08-08 18:01 ` Richard Stallman 1 sibling, 1 reply; 18+ messages in thread From: Richard Stallman @ 2006-08-08 18:01 UTC (permalink / raw) Cc: emacs-devel > To use the user's existing buffer would save the user's own unsaved > changes without asking. That is completely unacceptable. Is it completely unacceptable even if the file in question is principally "owned" by code anyway? Yes, I think so. If it is unlikely that users will edit the file by hand, that means there is unlikely to be a buffer to reuse. But IF there is a buffer to reuse, it means the user edited the file by hand. When he does so, you should not save his changes without his ok! I see other possibilities: 1. (and REUSE WRITE (buffer-modified-p #<buffer extant-buffer>) (error "Attempt to co-opt user's unsaved changes")) - that is, only allow REUSE and WRITE on an unmodified buffer. It is better to go ahead not reusing the buffer than to signal an error. 2. Go on modifying (because of WRITE) the buffer (because of REUSE), but don't save the changes at the end, or else ask the user whether to save them. That would be very inconvenient. There is no need to implement that option, and it would be better to avoid it for simplicity's sake. Either of these could be combined with a query beforehand: Any query will be an inconvenience. That's another reason now to implement these options. Complexity is a drawback, not a feature. I am looking for ways to simplify this. We should not reject them because of maybes. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-08-08 18:01 ` Richard Stallman @ 2006-08-08 18:32 ` Stuart D. Herring 2006-08-09 4:58 ` Richard Stallman 0 siblings, 1 reply; 18+ messages in thread From: Stuart D. Herring @ 2006-08-08 18:32 UTC (permalink / raw) Cc: emacs-devel > Is it completely unacceptable even if the file in question is > principally > "owned" by code anyway? > > Yes, I think so. If it is unlikely that users will edit the file by > hand, that means there is unlikely to be a buffer to reuse. But IF > there is a buffer to reuse, it means the user edited the file by hand. > When he does so, you should not save his changes without his ok! It means the user -visited- the file explicitly. He may or may not have been interested in changing it by hand. I don't know, however, if this distinction is important. > I see other possibilities: > 1. (and REUSE WRITE (buffer-modified-p #<buffer extant-buffer>) (error > "Attempt to co-opt user's unsaved changes")) - that is, only allow > REUSE > and WRITE on an unmodified buffer. > > It is better to go ahead not reusing the buffer than to signal an > error. Aha -- perhaps there's a good "compromise" here. What if REUSE is treated as nil if the extant buffer is modified and WRITE is non-nil? Since the file may be visited using the wrong literality, there is already no guarantee that REUSE "does anything", so it's not drastically different. There is still the problem of the user's unsaved changes clashing, but client code can always detect this eventuality if it's important, and it can happen anyway (the user could intend to C-x C-w another buffer into the file, or the literality condition could apply to a modified buffer, or...). It would be more consistent to categorically only reuse unmodified buffers -- but for just reading the file, it can make sense to see the user's changes (if any), and any program which wanted to avoid "unstable" file contents can just pass REUSE as nil anyway. The relevant section of the doc string would then read REUSE non-nil means to use an existing buffer if it is visiting FILE. (The value of `find-file-existing-other-name' affects this determination.) The buffer will only be re-used if its literal status (see `find-file-literally') corresponds to RAW. To avoid interacting with a user's unsaved changes, the buffer will be ignored if it is modified and WRITE is non-nil. Note that reusing a buffer may mean that the text on which BODY operates differs from the actual contents of FILE. Should I add a note that the user's buffer can become outdated as a result of failed or unattempted reuse of it? Davis -- This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-08-08 18:32 ` Stuart D. Herring @ 2006-08-09 4:58 ` Richard Stallman 0 siblings, 0 replies; 18+ messages in thread From: Richard Stallman @ 2006-08-09 4:58 UTC (permalink / raw) Cc: emacs-devel > Yes, I think so. If it is unlikely that users will edit the file by > hand, that means there is unlikely to be a buffer to reuse. But IF > there is a buffer to reuse, it means the user edited the file by hand. > When he does so, you should not save his changes without his ok! It means the user -visited- the file explicitly. He may or may not have been interested in changing it by hand. I don't know, however, if this distinction is important. If he didn't decide to change it by hand, then either (1) the buffer is unmodified, or (2) he changed it unwittingly. Aha -- perhaps there's a good "compromise" here. What if REUSE is treated as nil if the extant buffer is modified and WRITE is non-nil? It would work, but getting rid of the REUSE argument is much better because it makes this macro simpler to use. Should I add a note that the user's buffer can become outdated as a result of failed or unattempted reuse of it? No need. There are lots of ways a file could be changed on disk while it is visited in an Emacs buffer; there is no particular reason to distinguish this way from all the rest. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-08-07 21:38 ` Stuart D. Herring 2006-08-08 18:01 ` Richard Stallman @ 2006-08-08 18:01 ` Richard Stallman 2006-08-16 19:59 ` Stuart D. Herring 1 sibling, 1 reply; 18+ messages in thread From: Richard Stallman @ 2006-08-08 18:01 UTC (permalink / raw) Cc: emacs-devel OK, I've done my homework now. The querying function is `ask-user-about-supersession-threat'; it's called from lock_file() in filelock.c, which uses get_truename_buffer() to find the buffer whose modification time to examine. This means that if an existing buffer visiting the file is out of date, and get_truename_buffer() happens to return it instead of the up-to-date buffer created by `with-file', the supersession query will be raised. I see. When there is more than one candidate, get_truename_buffer picks the one that comes first in the buffer list. So the cleanest solution would be to make sure it always finds with-file's buffer. The simplest and most natural way is to put that buffer at the front of the buffer list. There are kludgy ways to do this from Lisp, but the cleanest way is just to make a primitive to do it. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-08-08 18:01 ` Richard Stallman @ 2006-08-16 19:59 ` Stuart D. Herring 2006-08-17 15:18 ` Richard Stallman 0 siblings, 1 reply; 18+ messages in thread From: Stuart D. Herring @ 2006-08-16 19:59 UTC (permalink / raw) Cc: emacs-devel > I see. When there is more than one candidate, get_truename_buffer > picks the one that comes first in the buffer list. So the cleanest > solution would be to make sure it always finds with-file's buffer. > > The simplest and most natural way is to put that buffer at the front > of the buffer list. There are kludgy ways to do this from Lisp, but > the cleanest way is just to make a primitive to do it. `record_buffer' does precisely this (along with promoting the buffer in its frame's list). Should this be made callable from Lisp so that such things as `with-file' can use it? Davis -- This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Missing `with' macro? 2006-08-16 19:59 ` Stuart D. Herring @ 2006-08-17 15:18 ` Richard Stallman 0 siblings, 0 replies; 18+ messages in thread From: Richard Stallman @ 2006-08-17 15:18 UTC (permalink / raw) Cc: emacs-devel `record_buffer' does precisely this (along with promoting the buffer in its frame's list). Should this be made callable from Lisp so that such things as `with-file' can use it? Yes, I think so. But let's do it after the release. ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2006-08-17 15:18 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-07-24 10:17 Missing `with' macro? Mathias Dahl 2006-07-24 13:46 ` Stefan Monnier 2006-07-24 14:33 ` Mathias Dahl 2006-07-24 18:22 ` Richard Stallman 2006-07-24 20:55 ` Jorgen Schaefer 2006-07-25 3:09 ` Richard Stallman 2006-07-28 2:14 ` Stuart D. Herring 2006-07-28 2:23 ` Stuart D. Herring 2006-07-29 15:18 ` Richard Stallman 2006-08-01 1:06 ` Stuart D. Herring 2006-08-07 5:01 ` Richard Stallman 2006-08-07 21:38 ` Stuart D. Herring 2006-08-08 18:01 ` Richard Stallman 2006-08-08 18:32 ` Stuart D. Herring 2006-08-09 4:58 ` Richard Stallman 2006-08-08 18:01 ` Richard Stallman 2006-08-16 19:59 ` Stuart D. Herring 2006-08-17 15:18 ` Richard Stallman
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.