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?

lawlist
  • 19,106
  • 5
  • 38
  • 120

1 Answers1

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)))))
Omar
  • 4,812
  • 1
  • 18
  • 33
  • 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 03 '21 at 01: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 03 '21 at 01: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 03 '21 at 01: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 03 '21 at 02:17