1

The buffer contains a mixture of text that is read-only (with 'read-only text properties) and read-write (i.e., no 'read-only text properties). I want to [up/down]case-region as to the read-write sections, but am unable to do so due to the 'read-only sections. How can I [up/down]case everything that is read-write within the defined BEG/END of the region, skipping the read-only text, and not yielding any error message?

2

You could use this command:

(defun on-writeable-portions (fn beg end)
  "Call FN on all writeable subregions of BEG - END."
  (interactive "CCommand: \nr")
  (when (get-text-property beg 'read-only)
    (setq beg (next-single-property-change beg 'read-only nil (1+ end))))
  (while (< beg end)
    (let ((lim (next-single-property-change beg 'read-only nil (1+ end))))
      (funcall fn beg (1- lim))
      (setq beg
            (if (< lim end)
                (next-single-property-change lim 'read-only nil (1+ end))
              end)))))
4
  • 1
    The use-case of this function will undoubtedly vary. In my particular use case, there is a wdired-mode buffer with a variety of files containing absolute paths. The filename-non-directory is read-only along with the the file-attributes, but the base-file-name is read-write. The function on-writeable-portions skips the last letter of the base-file-name at the end of each line in the region. I don't know whether my workaround creates issues with other applications, but the workaround I chose was to change (1- lim) to just lim. With that change, it works as expected.
    – lawlist
    Feb 3 at 1:05
  • 1
    ... I checked the text properties at the end of the line and that is where read-only begins anew; i.e., just before \n and just after the last character on the line (which in my case is the tail end of the base-file-name). I may decide to go ahead and modify the wdired-mode code to begin read-only at the beginning of the next line so that the \n has no text properties, but I'll probably also keep the modification in the previous comment. You have been a big help and I've added your function to a couple of keyboard shortcuts in wdired-mode ...
    – lawlist
    Feb 3 at 1:16
  • 1
    I have since changed the mod from (1- lim) to lim to (min lim (point-max)), the latter of which avoids an args-out-of-range if the region extends to the end of the buffer ...
    – lawlist
    Feb 3 at 1:38
  • I'm glad you could fix the off-by-one error and the bug at the end of the buffer, @lawlist, I didn't do much testing before answering.
    – Omar
    Feb 3 at 2:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.