From: Eli Zaretskii Date: Thu, 17 Aug 2023 07:07:48 +0000 (+0300) Subject: Improve documentation of case transfer in replacement commands X-Git-Tag: emacs-29.1.90~196 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=636fb267c46f62c89bc34b7de1c78a25c0b20f37;p=emacs.git Improve documentation of case transfer in replacement commands * doc/emacs/search.texi (Replacement and Lax Matches): * src/search.c (Freplace_match): * lisp/replace.el (query-replace, query-replace-regexp): Clarify in the doc string and the manual how letter-case is transferred from the replaced text to the replacement text. (Bug#65347) --- diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi index 45378d95f65..e5542a0fcf3 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -1658,6 +1658,7 @@ command's first argument. If @code{case-fold-search} is set to @code{nil}, case is always significant in all searches. @vindex case-replace +@cindex case preservation in replace commands In addition, when the second argument of a replace command is all or partly lower case, replacement commands try to preserve the case pattern of each occurrence. Thus, the command @@ -1671,7 +1672,27 @@ replaces a lower case @samp{foo} with a lower case @samp{bar}, an all-caps @samp{FOO} with @samp{BAR}, and a capitalized @samp{Foo} with @samp{Bar}. (These three alternatives---lower case, all caps, and capitalized, are the only ones that @code{replace-string} can -distinguish.) +distinguish.) Note that Emacs decides whether to up-case or capitalize +the replacement text by analyzing each word in the text being +replaced, and will preserve the letter-case of the replaced text only +if @emph{all} of its words use the same letter-case. Thus, the +command + +@example +M-x replace-string @key{RET} foo bar @key{RET} baz quux @key{RET} +@end example + +@noindent +replaces @samp{Foo Bar} with @samp{Baz Quux} because both words in +@samp{Foo Bar} are capitalized. By contrast, the same command +replaces @samp{Foo bar} with @samp{baz quux}, i.e.@: it leaves the +letter-case of the replacement text unchanged, since the two words in +@samp{Foo bar} use different capitalization. What exactly is +considered a ``word'' depends on the syntax tables that are in effect +in the current buffer (@pxref{Syntax Tables,,, elisp, The Emacs Lisp +Reference Manual}); thus, @samp{Foo_Bar} is two words in Text mode, +but could be a single word in some major mode that supports a +programming language. If upper-case letters are used in the replacement string, they remain upper case every time that text is inserted. If upper-case letters are @@ -1708,7 +1729,7 @@ This command finds occurrences of @samp{foo} one by one, displays each occurrence and asks you whether to replace it. Aside from querying, @code{query-replace} works just like @code{replace-string} (@pxref{Unconditional Replace}). In particular, it preserves case -provided @code{case-replace} is non-@code{nil}, as it normally is +provided that @code{case-replace} is non-@code{nil}, as it normally is (@pxref{Replacement and Lax Matches}). A numeric argument means to consider only occurrences that are bounded by word-delimiter characters. A negative prefix argument replaces backward. diff --git a/lisp/replace.el b/lisp/replace.el index 1555731f6e3..eeac734f3bd 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -417,8 +417,9 @@ Replacement transfers the case pattern of the old text to the new text, if both `case-fold-search' and `case-replace' are non-nil and FROM-STRING has no uppercase letters. \(Transferring the case pattern means that if the old text -matched is all caps, or capitalized, then its replacement is -respectively upcased or capitalized.) +matched is all caps, or all of its words are capitalized, then its +replacement is respectively upcased or capitalized. For more +details about this, see `replace-match'.) Ignore read-only matches if `query-replace-skip-read-only' is non-nil, ignore hidden matches if `search-invisible' is nil, and ignore more @@ -492,8 +493,9 @@ there are uppercase letters in REGEXP. Replacement transfers the case pattern of the old text to the new text, if both `case-fold-search' and `case-replace' are non-nil and REGEXP has no uppercase letters. (Transferring the case pattern -means that if the old text matched is all caps, or capitalized, -then its replacement is respectively upcased or capitalized.) +means that if the old text matched is all caps, or all of its words +are capitalized, then its replacement is respectively upcased or +capitalized. For more details about this, see `replace-match'.) Ignore read-only matches if `query-replace-skip-read-only' is non-nil, ignore hidden matches if `search-invisible' is nil, and ignore more diff --git a/src/search.c b/src/search.c index 0bb52c03eef..25c68f0788c 100644 --- a/src/search.c +++ b/src/search.c @@ -2359,7 +2359,9 @@ the replacement text. Otherwise, maybe capitalize the whole text, or maybe just word initials, based on the replaced text. If the replaced text has only capital letters and has at least one multiletter word, convert NEWTEXT to all caps. Otherwise if all words are capitalized -in the replaced text, capitalize each word in NEWTEXT. +in the replaced text, capitalize each word in NEWTEXT. Note that +what exactly is a word is determined by the syntax tables in effect +in the current buffer. If optional third arg LITERAL is non-nil, insert NEWTEXT literally. Otherwise treat `\\' as special: