4

I have a read-only file that I open in Emacs. I have created a keyboard shortcut to hide some regions of the file. For example:

(defun hide-beginning ()
  (interactive)
  (setq buffer-read-only nil)
  (put-text-property 1 10 'invisible t)
  (setq buffer-read-only t)
  )

However, when I exit the buffer with kill-buffer or rather ido-kill-buffer, I get the question

Buffer myfile.txt modified; kill anyway? (yes or no)

How can this question be avoided?

Håkon Hægland
  • 3,608
  • 1
  • 20
  • 51
  • 1
    If you only care about changes that occur in this function, you can probably use `buffer-modified-p` and `set-buffer-modified-p` to store the modified state and restore it after changing the properties. – ChrisR Dec 02 '14 at 19:59
  • Thanks it works perfectly! I just put `(set-buffer-modified-p nil)` after I changed the property.. – Håkon Hægland Dec 02 '14 at 20:02
  • @ChrisR: I didn't see your comment before posting. Could you post your comment as an answer so that it could be accepted? – Dan Dec 02 '14 at 20:05
  • 1
    @HåkonHægland You might want to save value of calling `buffer-modified-p` at the beginning of the function. That way, if something else modifies the buffer, you will still be prompted about it. – zck Dec 02 '14 at 21:36
  • If you're setting text properties which aren't meant to be saved in a file or copied and yanked, you should probably use [overlays](http://www.gnu.org/software/emacs/manual/html_node/elisp/Overlays.html#Overlays) instead of text properties. See also [What are overlays for, and how do they differ from text properties?](http://emacs.stackexchange.com/questions/2200/what-are-overlays-for-and-how-do-they-differ-from-text-properties) – Gilles 'SO- stop being evil' Dec 04 '14 at 02:20

3 Answers3

5

If you only care about changes that occur in this function, you can use buffer-modified-p and set-buffer-modified-p to store the modified state and restore it after changing the properties.

ChrisR
  • 404
  • 2
  • 7
2

The manual notes that you can use set-buffer-modified-p with a nil argument to flag the buffer as unmodified. Hence, if you want your function not to modify the buffer, you could do the following:

(defun hide-beginning ()
  (interactive)
  (let ((buffer-read-only nil)
        (buffer-modified (buffer-modified-p)))
    (put-text-property 1 10 'invisible t)
    (set-buffer-modified-p buffer-modified)))
Dan
  • 32,584
  • 6
  • 98
  • 168
  • Thanks! Don't you need to restore `buffer-read-only` at the end of the function? – Håkon Hægland Dec 02 '14 at 20:09
  • 1
    @HåkonHægland: when you `let`-bind `buffer-read-only`, you are binding it dynamically for the lifespan of the function -- basically, you're temporarily overriding its value. – Dan Dec 02 '14 at 20:12
  • 2
    @HåkonHægland the best approach is to letbind `inhibit-read-only` to t. That will cover more cases than just setting buffer-read-only to nil. – Malabarba Dec 02 '14 at 20:48
  • 2
    Unconditionally marking the buffer as unmodified is very dangerous. You should do that only if the buffer was unmodified in the first place, otherwise this has a high risk of resulting in unsaved changes sooner or later. – Gilles 'SO- stop being evil' Dec 04 '14 at 00:23
2

The macro with-silent-modifications (in subr.el) seems to exist for exactly this use case:

Execute BODY, pretending it does not modify the buffer.
...
Typically used around modifications of text-properties which do
not really affect the buffer's content.
glucas
  • 20,175
  • 1
  • 51
  • 83