summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2023-08-17 10:07:48 +0300
committerEli Zaretskii <eliz@gnu.org>2023-08-17 10:07:48 +0300
commit636fb267c46f62c89bc34b7de1c78a25c0b20f37 (patch)
treeb3a91d9dc4185530000a22b918afc8f312623656
parent7856d51436b759aa03ac2b32126d177cebbbca8c (diff)
downloademacs-636fb267c46f62c89bc34b7de1c78a25c0b20f37.tar.gz
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)
-rw-r--r--doc/emacs/search.texi25
-rw-r--r--lisp/replace.el10
-rw-r--r--src/search.c4
3 files changed, 32 insertions, 7 deletions
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: