How about using keyboard macros:
- <f3> -- start recording
- C-M-s
\b[A-Z]\{2,\}\b
RET -- find the next word of only upper-case letters and at least 2 letters.
- M--M-c -- Call
capitalize-word
on the word before point
- M-0<f4> -- Stop recording and run the macro repeatedly until error
n.b. If that's catching non-upper-case words as well, you'd need to set isearch-case-fold-search
.
Or more directly (and you could run this via M-: as a one-time thing, or make a new interactive function if you want to re-use it):
(let ((case-fold-search nil))
(while (re-search-forward "\\b[A-Z]\\{2,\\}\\b" nil :noerror)
(capitalize-word -1)))
Regarding comments, some corner cases may well need custom attention, but Emacs does have you covered on the matter of diacritics, as we can simply use [[:upper:]]
in place of [A-Z]
.
The following kind of modification might be worth trying to catch the other elements:
(let ((case-fold-search nil)
(pattern "\\(?:\\b\\|Ma?c\\|'\\)\\([[:upper:]]\\{2,\\}\\)\\b"))
(while (re-search-forward pattern nil :noerror)
(save-restriction
(narrow-to-region (match-beginning 1) (match-end 1))
(capitalize-word -1))))
but perhaps it's good enough to simply relax the pattern to:
"\\([[:upper:]]\\{2,\\}\\)\\b"