Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emacs: How to intelligently handle buffer-modified when setting text properties?

Tags:

emacs

The documentation on Text Properties says:

Since text properties are considered part of the contents of the buffer (or string), and can affect how a buffer looks on the screen, any change in buffer text properties marks the buffer as modified.

First, I don't understand that policy. Can anyone explain? The text props are not actually saved in the file, when the buffer is saved. So why mark the buffer as modified? For me, buffer-modified indicates "some changes have not yet been saved." but understanding the policy is just for my own amusement.

More importantly, is there an already-established way that, in code, I can change syntax text properties on the text in a buffer, while keeping the buffer-modified flag set to whatever it was, prior to those changes? I'm thinking of something like save-excursion. It would be pretty easy to write, but this seems like a common case and I'd like to use the standard function, if possible.

For more on the scenario - I have a mode that does a full text scan and sets syntax-table properties on the text. After opening a buffer, the scan runs, but it results in a buffer with buffer-modified set to t .

As always, thanks.

like image 733
Cheeso Avatar asked Apr 23 '10 15:04

Cheeso


2 Answers

Newer versions of Emacs include the macro "with-silent-modifications" for this:

C-h f with-silent-modifications
------------------------------------------------------
with-silent-modifications is a Lisp macro in `subr.el'.

(with-silent-modifications &rest BODY)

Execute BODY, pretending it does not modify the buffer.
If BODY performs real modifications to the buffer's text, other
than cosmetic ones, undo data may become corrupted.
Typically used around modifications of text-properties which do not really
affect the buffer's content.
like image 179
Jeremy Rayman Avatar answered Oct 17 '22 19:10

Jeremy Rayman


Wait! I found this in cc-defs.el

;; The following is essentially `save-buffer-state' from lazy-lock.el.
;; It ought to be a standard macro.
(defmacro c-save-buffer-state (varlist &rest body)
  "Bind variables according to VARLIST (in `let*' style) and eval BODY,
then restore the buffer state under the assumption that no significant
modification has been made in BODY.  A change is considered
significant if it affects the buffer text in any way that isn't
completely restored again.  Changes in text properties like `face' or
`syntax-table' are considered insignificant.  This macro allows text
properties to be changed, even in a read-only buffer.

This macro should be placed around all calculations which set
\"insignificant\" text properties in a buffer, even when the buffer is
known to be writeable.  That way, these text properties remain set
even if the user undoes the command which set them.

This macro should ALWAYS be placed around \"temporary\" internal buffer
changes \(like adding a newline to calculate a text-property then
deleting it again\), so that the user never sees them on his
`buffer-undo-list'.  See also `c-tentative-buffer-changes'.

However, any user-visible changes to the buffer \(like auto-newlines\)
must not be within a `c-save-buffer-state', since the user then
wouldn't be able to undo them.

The return value is the value of the last form in BODY."
  `(let* ((modified (buffer-modified-p)) (buffer-undo-list t)
          (inhibit-read-only t) (inhibit-point-motion-hooks t)
          before-change-functions after-change-functions
          deactivate-mark
          buffer-file-name buffer-file-truename ; Prevent primitives checking
                                                ; for file modification
          ,@varlist)
     (unwind-protect
         (progn ,@body)
       (and (not modified)
            (buffer-modified-p)
            (set-buffer-modified-p nil)))))
like image 35
Cheeso Avatar answered Oct 17 '22 19:10

Cheeso