aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2016-05-05 23:11:11 -0700
committerPaul Eggert2016-05-05 23:11:11 -0700
commit89ce83b20249dfb4e45f09dfdddf4c4b66d82968 (patch)
tree3d75245a5514df2ad7b17ae6d56727b9629846a9
parentd546ed13b04521308ef7ec8e7e5b68e03f1bbb38 (diff)
parent50650cb6887d99b01eeb1e686fc1f695c2a0c64a (diff)
downloademacs-89ce83b20249dfb4e45f09dfdddf4c4b66d82968.tar.gz
emacs-89ce83b20249dfb4e45f09dfdddf4c4b66d82968.zip
Merge from origin/emacs-25
50650cb Doc fixes for fclist and grep 5e814e0 Minor doc fixes for quoting 3347a73 `nreverse' the marker pairs list 1a4127d Use save-excursion in xref-location-marker more ab3ba91 shell-quote-argument DIR when appropriate 922c7a3 Rework xref-query-replace-in-results 3fe3510 * lisp/replace.el (query-replace-read-from): Use minibuffer-w... 0932b94 Fix todo-mode bug involving archived items (bug#23447) e68ad1f ; * etc/NEWS: Tiny edit. (Bug#23432) adc80b7 ; * test/automated/xref-tests.el: Add copyright and license. 4d8fd9c Handle "empty line" regexp in xref searches f559b37 Add tests for xref-collect-matches 6428aa0 Use grep-find-ignored-directories instead of vc-directory-exc... 6f82d8e Clear buffer-undo-list when showing xrefs c68a091 Note the quote translation in `message' in section "incompati... 52f86a7 * etc/NEWS: Mention (message "%s" (format ...)). 93703c5 (Common Keywords): Correct what missing :group means 79e5800 Improve documentation of Dired's 'A' and 'Q' commands 2ea2a2f Doc fixes for quoting 8544b98 posnp doc clarification 805204f Mention what a missing :group does ec554d7 Fix documentation of dired-aux search/replace commands
-rw-r--r--doc/emacs/dired.texi14
-rw-r--r--doc/emacs/frames.texi5
-rw-r--r--doc/emacs/text.texi4
-rw-r--r--doc/lispintro/emacs-lisp-intro.texi28
-rw-r--r--doc/lispref/control.texi11
-rw-r--r--doc/lispref/customize.texi9
-rw-r--r--doc/lispref/display.texi11
-rw-r--r--doc/lispref/help.texi4
-rw-r--r--doc/lispref/strings.texi10
-rw-r--r--etc/NEWS23
-rw-r--r--etc/PROBLEMS2
-rw-r--r--lisp/calendar/todo-mode.el39
-rw-r--r--lisp/cedet/cedet-cscope.el2
-rw-r--r--lisp/cedet/semantic/symref.el2
-rw-r--r--lisp/dired-aux.el19
-rw-r--r--lisp/man.el2
-rw-r--r--lisp/progmodes/elisp-mode.el5
-rw-r--r--lisp/progmodes/etags.el5
-rw-r--r--lisp/progmodes/project.el3
-rw-r--r--lisp/progmodes/xref.el146
-rw-r--r--lisp/replace.el21
-rw-r--r--lisp/subr.el15
-rw-r--r--src/bidi.c4
-rw-r--r--src/callint.c2
-rw-r--r--src/doprnt.c6
-rw-r--r--src/editfns.c13
-rw-r--r--test/automated/data/xref/file1.txt2
-rw-r--r--test/automated/data/xref/file2.txt2
-rw-r--r--test/automated/xref-tests.el91
29 files changed, 343 insertions, 157 deletions
diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi
index 68c6813c242..486e92a40bb 100644
--- a/doc/emacs/dired.texi
+++ b/doc/emacs/dired.texi
@@ -795,6 +795,14 @@ This command is a variant of @code{xref-find-references}
795where you can navigate between matches and display them as needed 795where you can navigate between matches and display them as needed
796using the commands described in @ref{Xref Commands}. 796using the commands described in @ref{Xref Commands}.
797 797
798@vindex grep-find-ignored-files @r{(Dired)}
799@vindex grep-find-ignored-directories @r{(Dired)}
800If any of the marked files are directories, then this command searches
801all of the files in those directories, and any of their
802subdirectories, recursively, except files whose names match
803@code{grep-find-ignored-files} and subdirectories whose names match
804@code{grep-find-ignored-directories}.
805
798@kindex Q @r{(Dired)} 806@kindex Q @r{(Dired)}
799@findex dired-do-find-regexp-and-replace 807@findex dired-do-find-regexp-and-replace
800@cindex search and replace in multiple files (in Dired) 808@cindex search and replace in multiple files (in Dired)
@@ -809,6 +817,12 @@ and you can use the special commands in that buffer (@pxref{Xref
809Commands}). In particular, if you exit the query replace loop, you 817Commands}). In particular, if you exit the query replace loop, you
810can use @kbd{r} in that buffer to replace more matches. 818can use @kbd{r} in that buffer to replace more matches.
811@xref{Identifier Search}. 819@xref{Identifier Search}.
820
821Like with @code{dired-do-find-regexp}, if any of the marked files are
822directories, this command performs replacements in all of the files in
823those directories, and in any of their subdirectories, recursively,
824except for files whose names match @code{grep-find-ignored-files} and
825subdirectories whose names match @code{grep-find-ignored-directories}.
812@end table 826@end table
813 827
814@node Shell Commands in Dired 828@node Shell Commands in Dired
diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi
index 23ccd6a8f41..a7e709f9221 100644
--- a/doc/emacs/frames.texi
+++ b/doc/emacs/frames.texi
@@ -764,7 +764,8 @@ Fontconfig fonts, you can use the @command{fc-list} command to list
764the available fixed-width fonts, like this: 764the available fixed-width fonts, like this:
765 765
766@example 766@example
767fc-list :spacing=mono fc-list :spacing=charcell 767fc-list :spacing=mono
768fc-list :spacing=charcell
768@end example 769@end example
769 770
770@noindent 771@noindent
@@ -772,7 +773,7 @@ For server-side X fonts, you can use the @command{xlsfonts} program to
772list the available fixed-width fonts, like this: 773list the available fixed-width fonts, like this:
773 774
774@example 775@example
775xlsfonts -fn '*x*' | egrep "^[0-9]+x[0-9]+" 776xlsfonts -fn '*x*' | grep -E '^[0-9]+x[0-9]+'
776xlsfonts -fn '*-*-*-*-*-*-*-*-*-*-*-m*' 777xlsfonts -fn '*-*-*-*-*-*-*-*-*-*-*-m*'
777xlsfonts -fn '*-*-*-*-*-*-*-*-*-*-*-c*' 778xlsfonts -fn '*-*-*-*-*-*-*-*-*-*-*-c*'
778@end example 779@end example
diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi
index 66f01b495d1..579f7880cfe 100644
--- a/doc/emacs/text.texi
+++ b/doc/emacs/text.texi
@@ -862,8 +862,8 @@ indenting the current line. @xref{Indentation}, for details.
862 862
863 Text mode turns off the features concerned with comments except when 863 Text mode turns off the features concerned with comments except when
864you explicitly invoke them. It changes the syntax table so that 864you explicitly invoke them. It changes the syntax table so that
865single-quotes are considered part of words (e.g., @samp{don't} is 865apostrophes are considered part of words (e.g., @samp{don't} is
866considered one word). However, if a word starts with a single-quote, 866considered one word). However, if a word starts with an apostrophe,
867it is treated as a prefix for the purposes of capitalization 867it is treated as a prefix for the purposes of capitalization
868(e.g., @kbd{M-c} converts @samp{'hello'} into @samp{'Hello'}, as 868(e.g., @kbd{M-c} converts @samp{'hello'} into @samp{'Hello'}, as
869expected). 869expected).
diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index 78c1865703e..eea46af6b19 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -1004,11 +1004,11 @@ the name stands for ``Lots of Isolated Silly Parentheses''. But the
1004claim is unwarranted. Lisp stands for LISt Processing, and the 1004claim is unwarranted. Lisp stands for LISt Processing, and the
1005programming language handles @emph{lists} (and lists of lists) by 1005programming language handles @emph{lists} (and lists of lists) by
1006putting them between parentheses. The parentheses mark the boundaries 1006putting them between parentheses. The parentheses mark the boundaries
1007of the list. Sometimes a list is preceded by a single apostrophe or 1007of the list. Sometimes a list is preceded by an apostrophe @samp{'},
1008quotation mark, @samp{'}@footnote{The single apostrophe or quotation 1008called a @dfn{single-quote} in Lisp.@footnote{A single-quote is an
1009mark is an abbreviation for the function @code{quote}; you need not 1009abbreviation for the special form @code{quote}; you need not think
1010think about functions now; functions are defined in @ref{Making 1010about special forms now. @xref{Complications}.} Lists are the basis
1011Errors, , Generate an Error Message}.} Lists are the basis of Lisp. 1011of Lisp.
1012 1012
1013@menu 1013@menu
1014* Lisp Lists:: What are lists? 1014* Lisp Lists:: What are lists?
@@ -2490,14 +2490,7 @@ in the list and then at the function definition bound to that symbol.
2490Then the instructions in the function definition are carried out. 2490Then the instructions in the function definition are carried out.
2491 2491
2492@item 2492@item
2493A single quotation mark, 2493A single-quote @samp{'} tells the Lisp interpreter that it should
2494@ifinfo
2495'
2496@end ifinfo
2497@ifnotinfo
2498@code{'}
2499@end ifnotinfo
2500, tells the Lisp interpreter that it should
2501return the following expression as written, and not evaluate it as it 2494return the following expression as written, and not evaluate it as it
2502would if the quote were not there. 2495would if the quote were not there.
2503 2496
@@ -7610,7 +7603,8 @@ displays in which grave accent and apostrophe were often mirror images
7610suitable for use as quotes. On most modern displays this is no longer 7603suitable for use as quotes. On most modern displays this is no longer
7611true, and when these two ASCII characters appear in documentation 7604true, and when these two ASCII characters appear in documentation
7612strings or diagnostic message formats, Emacs typically transliterates 7605strings or diagnostic message formats, Emacs typically transliterates
7613them to curved single quotes, so that the abovequoted symbol appears 7606them to @dfn{curved quotes} (left and right single quotation marks),
7607so that the abovequoted symbol appears
7614as @t{‘case-fold-search’}. Source-code strings can also simply use 7608as @t{‘case-fold-search’}. Source-code strings can also simply use
7615curved quotes directly. 7609curved quotes directly.
7616 7610
@@ -17117,7 +17111,7 @@ This line is a short, but complete Emacs Lisp expression.
17117 17111
17118We are already familiar with @code{setq}. It sets the following variable, 17112We are already familiar with @code{setq}. It sets the following variable,
17119@code{major-mode}, to the subsequent value, which is @code{text-mode}. 17113@code{major-mode}, to the subsequent value, which is @code{text-mode}.
17120The single quote mark before @code{text-mode} tells Emacs to deal directly 17114The single-quote before @code{text-mode} tells Emacs to deal directly
17121with the @code{text-mode} symbol, not with whatever it might stand for. 17115with the @code{text-mode} symbol, not with whatever it might stand for.
17122@xref{set & setq, , Setting the Value of a Variable}, 17116@xref{set & setq, , Setting the Value of a Variable},
17123for a reminder of how @code{setq} works. 17117for a reminder of how @code{setq} works.
@@ -17284,11 +17278,11 @@ Rebinding Keys in Your Init File, emacs, The GNU Emacs Manual}, for
17284details.) 17278details.)
17285 17279
17286The command invoked by the keys is @code{compare-windows}. Note that 17280The command invoked by the keys is @code{compare-windows}. Note that
17287@code{compare-windows} is preceded by a single quote; otherwise, Emacs 17281@code{compare-windows} is preceded by a single-quote; otherwise, Emacs
17288would first try to evaluate the symbol to determine its value. 17282would first try to evaluate the symbol to determine its value.
17289 17283
17290These three things, the double quotation marks, the backslash before 17284These three things, the double quotation marks, the backslash before
17291the @samp{C}, and the single quote mark are necessary parts of 17285the @samp{C}, and the single-quote are necessary parts of
17292keybinding that I tend to forget. Fortunately, I have come to 17286keybinding that I tend to forget. Fortunately, I have come to
17293remember that I should look at my existing @file{.emacs} file, and 17287remember that I should look at my existing @file{.emacs} file, and
17294adapt what is there. 17288adapt what is there.
diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 3f48c458c02..0cdb03548bf 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -1100,10 +1100,13 @@ These examples show typical uses of @code{error}:
1100error symbol @code{error}, and a list containing the string returned by 1100error symbol @code{error}, and a list containing the string returned by
1101@code{format-message}. 1101@code{format-message}.
1102 1102
1103In a format string containing single quotes, curved quotes @t{‘like 1103The @code{text-quoting-style} variable controls what quotes are
1104this’} and grave quotes @t{`like this'} work better than straight 1104generated; @xref{Keys in Documentation}. A call using a format like
1105quotes @t{'like this'}, as @code{error} typically formats every 1105@t{"Missing `%s'"} with grave accents and apostrophes typically
1106straight quote as a curved closing quote. 1106generates a message like @t{"Missing ‘foo’"} with matching curved
1107quotes. In contrast, a call using a format like @t{"Missing '%s'"}
1108with only apostrophes typically generates a message like @t{"Missing
1109’foo’"} with only closing curved quotes, an unusual style in English.
1107 1110
1108@strong{Warning:} If you want to use your own string as an error message 1111@strong{Warning:} If you want to use your own string as an error message
1109verbatim, don't just write @code{(error @var{string})}. If @var{string} 1112verbatim, don't just write @code{(error @var{string})}. If @var{string}
diff --git a/doc/lispref/customize.texi b/doc/lispref/customize.texi
index 14e6eb3ab25..4a6f7f2162b 100644
--- a/doc/lispref/customize.texi
+++ b/doc/lispref/customize.texi
@@ -66,9 +66,12 @@ cause confusion.}
66 66
67@kindex group@r{, customization keyword} 67@kindex group@r{, customization keyword}
68@item :group @var{group} 68@item :group @var{group}
69Put this customization item in group @var{group}. When you use 69Put this customization item in group @var{group}. If this keyword is
70@code{:group} in a @code{defgroup}, it makes the new group a subgroup of 70missing from a customization item, it'll be placed in the same group
71@var{group}. 71that was last defined (in the current file).
72
73When you use @code{:group} in a @code{defgroup}, it makes the new
74group a subgroup of @var{group}.
72 75
73If you use this keyword more than once, you can put a single item into 76If you use this keyword more than once, you can put a single item into
74more than one group. Displaying any of those groups will show this 77more than one group. Displaying any of those groups will show this
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 3673d114041..87126f9167a 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -265,10 +265,13 @@ properties, it is displayed with the specified faces (@pxref{Faces}).
265The string is also added to the @file{*Messages*} buffer, but without 265The string is also added to the @file{*Messages*} buffer, but without
266text properties (@pxref{Logging Messages}). 266text properties (@pxref{Logging Messages}).
267 267
268In a format string containing single quotes, curved quotes @t{‘like 268The @code{text-quoting-style} variable controls what quotes are
269this’} and grave quotes @t{`like this'} work better than straight 269generated; @xref{Keys in Documentation}. A call using a format like
270quotes @t{'like this'}, as @code{message} typically formats every 270@t{"Missing `%s'"} with grave accents and apostrophes typically
271straight quote as a curved closing quote. 271generates a message like @t{"Missing ‘foo’"} with matching curved
272quotes. In contrast, a call using a format like @t{"Missing '%s'"}
273with only apostrophes typically generates a message like @t{"Missing
274’foo’"} with only closing curved quotes, an unusual style in English.
272 275
273In batch mode, the message is printed to the standard error stream, 276In batch mode, the message is printed to the standard error stream,
274followed by a newline. 277followed by a newline.
diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi
index 58a11f29a4c..b945e438f55 100644
--- a/doc/lispref/help.texi
+++ b/doc/lispref/help.texi
@@ -335,10 +335,14 @@ specifies @var{mapvar}'s value as the keymap for any following
335@item ‘ 335@item ‘
336@itemx ` 336@itemx `
337(left single quotation mark and grave accent) both stand for a left quote. 337(left single quotation mark and grave accent) both stand for a left quote.
338This generates a left single quotation mark, an apostrophe, or a grave
339accent depending on the value of @code{text-quoting-style}.
338 340
339@item ’ 341@item ’
340@itemx ' 342@itemx '
341(right single quotation mark and apostrophe) both stand for a right quote. 343(right single quotation mark and apostrophe) both stand for a right quote.
344This generates a right single quotation mark or an apostrophe
345depending on the value of @code{text-quoting-style}.
342 346
343@item \= 347@item \=
344quotes the following character and is discarded; thus, @samp{\=`} puts 348quotes the following character and is discarded; thus, @samp{\=`} puts
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index ce629aa8259..58ab02dbc41 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -842,8 +842,14 @@ if any.
842This function acts like @code{format}, except it also converts any 842This function acts like @code{format}, except it also converts any
843curved single quotes in @var{string} as per the value of 843curved single quotes in @var{string} as per the value of
844@code{text-quoting-style}, and treats grave accent (@t{`}) and 844@code{text-quoting-style}, and treats grave accent (@t{`}) and
845apostrophe (@t{'}) as if they were curved single quotes. @xref{Keys 845apostrophe (@t{'}) as if they were curved single quotes.
846in Documentation}. 846
847A format that quotes with grave accents and apostrophes @t{`like
848this'} typically generates curved quotes @t{‘like this’}. In
849contrast, a format that quotes with only apostrophes @t{'like this'}
850typically generates two closing curved quotes @t{’like this’}, an
851unusual style in English. @xref{Keys in Documentation}, for how the
852@code{text-quoting-style} variable affects generated quotes.
847@end defun 853@end defun
848 854
849@cindex @samp{%} in format 855@cindex @samp{%} in format
diff --git a/etc/NEWS b/etc/NEWS
index e2026121b95..29559d143db 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1917,6 +1917,14 @@ display of diagnostics and help, but not of info. As the variable is
1917not intended for casual use, it is not a user option. 1917not intended for casual use, it is not a user option.
1918 1918
1919+++ 1919+++
1920** Message-issuing functions like 'message' and 'error' now translate
1921various sorts of single quotes in their format strings according to
1922the value of 'text-quoting-style' (see above). This translation
1923cannot be disabled. To get the old behavior, use 'format', which is
1924not affected by 'text-quoting-style', e.g., (message "%s" (format
1925"...." foo bar)).
1926
1927+++
1920** substitute-command-keys now replaces quotes. 1928** substitute-command-keys now replaces quotes.
1921That is, it converts documentation strings' quoting style as per the 1929That is, it converts documentation strings' quoting style as per the
1922value of 'text-quoting-style'. Doc strings in source code can use 1930value of 'text-quoting-style'. Doc strings in source code can use
@@ -1924,13 +1932,6 @@ either curved single quotes or grave accents and apostrophes. As
1924before, characters preceded by \= are output as-is. 1932before, characters preceded by \= are output as-is.
1925 1933
1926+++ 1934+++
1927** Message-issuing functions 'error', 'message', etc. now convert quotes.
1928They use the new 'format-message' function instead of plain 'format',
1929so that they now follow user preference as per 'text-quoting-style'
1930when processing curved single quotes, grave accents, and apostrophes
1931in their format argument.
1932
1933+++
1934** The character classes [:alpha:] and [:alnum:] in regular expressions 1935** The character classes [:alpha:] and [:alnum:] in regular expressions
1935now match multibyte characters using Unicode character properties. 1936now match multibyte characters using Unicode character properties.
1936If you want the old behavior where they matched any character with 1937If you want the old behavior where they matched any character with
@@ -2148,9 +2149,11 @@ permissions set to temporary values (e.g., for creating private files).
2148 2149
2149--- 2150---
2150** Function 'system-name' now returns an updated value if the current 2151** Function 'system-name' now returns an updated value if the current
2151system's name has changed or if the Emacs process has changed systems, 2152system's name has changed or if the Emacs process has changed systems.
2152and to avoid long waits it no longer consults DNS to canonicalize the 2153To avoid long waits it no longer consults DNS to canonicalize the name
2153name. The variable 'system-name' is now obsolete. 2154(in some cases this may affect generated message-id headers - customize
2155'message-user-fqdn' if this bothers you). The variable 'system-name'
2156is now obsolete.
2154 2157
2155+++ 2158+++
2156** Function 'write-region' no longer outputs "Wrote FILE" in batch mode. 2159** Function 'write-region' no longer outputs "Wrote FILE" in batch mode.
diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index 4288808f407..49dada970bb 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -1624,7 +1624,7 @@ which combination produces "M-x" in the echo area. You can also use
1624the 'xmodmap' utility to show all the keys which produce a Meta 1624the 'xmodmap' utility to show all the keys which produce a Meta
1625modifier: 1625modifier:
1626 1626
1627 xmodmap -pk | egrep -i "meta|alt" 1627 xmodmap -pk | grep -Ei "meta|alt"
1628 1628
1629A more convenient way of finding out which keys produce a Meta modifier 1629A more convenient way of finding out which keys produce a Meta modifier
1630is to use the 'xkbprint' utility, if it's available on your system: 1630is to use the 'xkbprint' utility, if it's available on your system:
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index 0529e970333..8e752586053 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -902,17 +902,19 @@ Categories mode."
902 (todo-show) 902 (todo-show)
903 (let* ((archive (eq where 'archive)) 903 (let* ((archive (eq where 'archive))
904 (cat (unless archive where)) 904 (cat (unless archive where))
905 (goto-archive (and cat
906 todo-skip-archived-categories
907 (zerop (todo-get-count 'todo cat))
908 (zerop (todo-get-count 'done cat))
909 (not (zerop (todo-get-count 'archived cat)))))
905 (file0 (when cat ; We're in Todo Categories mode. 910 (file0 (when cat ; We're in Todo Categories mode.
906 ;; With non-nil `todo-skip-archived-categories' 911 (if goto-archive
907 ;; jump to archive file of a category with only 912 ;; If the category has only archived items and
908 ;; archived items. 913 ;; `todo-skip-archived-categories' is non-nil, jump to
909 (if (and todo-skip-archived-categories 914 ;; the archive category.
910 (zerop (todo-get-count 'todo cat))
911 (zerop (todo-get-count 'done cat))
912 (not (zerop (todo-get-count 'archived cat))))
913 (concat (file-name-sans-extension 915 (concat (file-name-sans-extension
914 todo-current-todo-file) ".toda") 916 todo-current-todo-file) ".toda")
915 ;; Otherwise, jump to current todo file. 917 ;; Otherwise, jump to the category in the todo file.
916 todo-current-todo-file))) 918 todo-current-todo-file)))
917 (len (length todo-categories)) 919 (len (length todo-categories))
918 (cat+file (unless cat 920 (cat+file (unless cat
@@ -923,18 +925,15 @@ Categories mode."
923 (category (or cat (car cat+file)))) 925 (category (or cat (car cat+file))))
924 (unless cat (setq file0 (cdr cat+file))) 926 (unless cat (setq file0 (cdr cat+file)))
925 (with-current-buffer (find-file-noselect file0 'nowarn) 927 (with-current-buffer (find-file-noselect file0 'nowarn)
926 (setq todo-current-todo-file file0) 928 (when goto-archive (todo-archive-mode))
927 ;; If called from Todo Categories mode, clean up before jumping. 929 (set-window-buffer (selected-window)
928 (if (string= (buffer-name) todo-categories-buffer) 930 (set-buffer (find-buffer-visiting file0)))
929 (kill-buffer)) 931 (unless todo-global-current-todo-file
930 (set-window-buffer (selected-window) 932 (setq todo-global-current-todo-file todo-current-todo-file))
931 (set-buffer (find-buffer-visiting file0))) 933 (todo-category-number category)
932 (unless todo-global-current-todo-file 934 (todo-category-select)
933 (setq todo-global-current-todo-file todo-current-todo-file)) 935 (goto-char (point-min))
934 (todo-category-number category) 936 (when add-item (todo-insert-item--basic))))))
935 (todo-category-select)
936 (goto-char (point-min))
937 (when add-item (todo-insert-item--basic))))))
938 937
939(defun todo-next-item (&optional count) 938(defun todo-next-item (&optional count)
940 "Move point down to the beginning of the next item. 939 "Move point down to the beginning of the next item.
diff --git a/lisp/cedet/cedet-cscope.el b/lisp/cedet/cedet-cscope.el
index 9a54d341f56..373149c16e3 100644
--- a/lisp/cedet/cedet-cscope.el
+++ b/lisp/cedet/cedet-cscope.el
@@ -52,7 +52,7 @@ SCOPE is the scope of the search, such as 'project or 'subdirs."
52 ;; -0 = Find C symbol 52 ;; -0 = Find C symbol
53 ;; -1 = Find global definition 53 ;; -1 = Find global definition
54 ;; -3 = Find references 54 ;; -3 = Find references
55 ;; -6 = Find egrep pattern 55 ;; -6 = Find grep -E pattern
56 ;; -7 = Find file 56 ;; -7 = Find file
57 (let ((idx (cond ((eq type 'file) 57 (let ((idx (cond ((eq type 'file)
58 "-7") 58 "-7")
diff --git a/lisp/cedet/semantic/symref.el b/lisp/cedet/semantic/symref.el
index 088740b2624..516a4f30414 100644
--- a/lisp/cedet/semantic/symref.el
+++ b/lisp/cedet/semantic/symref.el
@@ -266,7 +266,7 @@ Returns an object of class `semantic-symref-result'."
266;;;###autoload 266;;;###autoload
267(defun semantic-symref-find-text (text &optional scope) 267(defun semantic-symref-find-text (text &optional scope)
268 "Find a list of occurrences of TEXT in the current project. 268 "Find a list of occurrences of TEXT in the current project.
269TEXT is a regexp formatted for use with egrep. 269TEXT is a regexp formatted for use with grep -E.
270Optional SCOPE specifies which file set to search. Defaults to `project'. 270Optional SCOPE specifies which file set to search. Defaults to `project'.
271Refers to `semantic-symref-tool', to determine the reference tool to use 271Refers to `semantic-symref-tool', to determine the reference tool to use
272for the current buffer. 272for the current buffer.
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index b23b04a45fa..8d6f6656a9a 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -2747,14 +2747,21 @@ with the command \\[tags-loop-continue]."
2747 2747
2748;;;###autoload 2748;;;###autoload
2749(defun dired-do-find-regexp (regexp) 2749(defun dired-do-find-regexp (regexp)
2750 "Find all matches for REGEXP in all marked files, recursively." 2750 "Find all matches for REGEXP in all marked files.
2751For any marked directory, all of its files are searched recursively.
2752However, files matching `grep-find-ignored-files' and subdirectories
2753matching `grep-find-ignored-directories' are skipped in the marked
2754directories.
2755
2756REGEXP should use constructs supported by your local `grep' command."
2751 (interactive "sSearch marked files (regexp): ") 2757 (interactive "sSearch marked files (regexp): ")
2752 (require 'grep) 2758 (require 'grep)
2753 (defvar grep-find-ignored-files) 2759 (defvar grep-find-ignored-files)
2760 (defvar grep-find-ignored-directories)
2754 (let* ((files (dired-get-marked-files)) 2761 (let* ((files (dired-get-marked-files))
2755 (ignores (nconc (mapcar 2762 (ignores (nconc (mapcar
2756 (lambda (s) (concat s "/")) 2763 (lambda (s) (concat s "/"))
2757 vc-directory-exclusion-list) 2764 grep-find-ignored-directories)
2758 grep-find-ignored-files)) 2765 grep-find-ignored-files))
2759 (xrefs (cl-mapcan 2766 (xrefs (cl-mapcan
2760 (lambda (file) 2767 (lambda (file)
@@ -2768,7 +2775,13 @@ with the command \\[tags-loop-continue]."
2768 2775
2769;;;###autoload 2776;;;###autoload
2770(defun dired-do-find-regexp-and-replace (from to) 2777(defun dired-do-find-regexp-and-replace (from to)
2771 "Replace matches of FROM with TO, in all marked files, recursively." 2778 "Replace matches of FROM with TO, in all marked files.
2779For any marked directory, matches in all of its files are replaced,
2780recursively. However, files matching `grep-find-ignored-files'
2781and subdirectories matching `grep-find-ignored-directories' are skipped
2782in the marked directories.
2783
2784REGEXP should use constructs supported by your local `grep' command."
2772 (interactive 2785 (interactive
2773 (let ((common 2786 (let ((common
2774 (query-replace-read-args 2787 (query-replace-read-args
diff --git a/lisp/man.el b/lisp/man.el
index 2b2ee99a9be..5acf90baf28 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -964,7 +964,7 @@ otherwise look like a page name.
964 964
965An \"apropos\" query with -k gives a buffer of matching page 965An \"apropos\" query with -k gives a buffer of matching page
966names or descriptions. The pattern argument is usually an 966names or descriptions. The pattern argument is usually an
967\"egrep\" style regexp. 967\"grep -E\" style regexp.
968 968
969 -k pattern" 969 -k pattern"
970 970
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 1c728484ab5..2ad22ddd0ff 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -823,8 +823,9 @@ non-nil result supercedes the xrefs produced by
823 (pcase-let (((cl-struct xref-elisp-location symbol type file) l)) 823 (pcase-let (((cl-struct xref-elisp-location symbol type file) l))
824 (let ((buffer-point (find-function-search-for-symbol symbol type file))) 824 (let ((buffer-point (find-function-search-for-symbol symbol type file)))
825 (with-current-buffer (car buffer-point) 825 (with-current-buffer (car buffer-point)
826 (goto-char (or (cdr buffer-point) (point-min))) 826 (save-excursion
827 (point-marker))))) 827 (goto-char (or (cdr buffer-point) (point-min)))
828 (point-marker))))))
828 829
829(cl-defmethod xref-location-group ((l xref-elisp-location)) 830(cl-defmethod xref-location-group ((l xref-elisp-location))
830 (xref-elisp-location-file l)) 831 (xref-elisp-location-file l))
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index a2a0df2d6e1..890d55294cf 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -2146,8 +2146,9 @@ for \\[find-tag] (which see)."
2146 (with-slots (tag-info file) l 2146 (with-slots (tag-info file) l
2147 (let ((buffer (find-file-noselect file))) 2147 (let ((buffer (find-file-noselect file)))
2148 (with-current-buffer buffer 2148 (with-current-buffer buffer
2149 (etags-goto-tag-location tag-info) 2149 (save-excursion
2150 (point-marker))))) 2150 (etags-goto-tag-location tag-info)
2151 (point-marker))))))
2151 2152
2152(cl-defmethod xref-location-line ((l xref-etags-location)) 2153(cl-defmethod xref-location-line ((l xref-etags-location))
2153 (with-slots (tag-info) l 2154 (with-slots (tag-info) l
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 9c8a88c80fc..a51c383b93b 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -172,7 +172,8 @@ to find the list of ignores for each directory."
172 (let ((command 172 (let ((command
173 (format "%s %s %s -type f -print0" 173 (format "%s %s %s -type f -print0"
174 find-program 174 find-program
175 dir 175 (shell-quote-argument
176 (expand-file-name dir))
176 (xref--find-ignores-arguments 177 (xref--find-ignores-arguments
177 (project-ignores project dir) 178 (project-ignores project dir)
178 (expand-file-name dir))))) 179 (expand-file-name dir)))))
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index b5632af13ab..f651dc9cd18 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -521,58 +521,86 @@ references displayed in the current *xref* buffer."
521 (let ((fr (read-regexp "Xref query-replace (regexp)" ".*"))) 521 (let ((fr (read-regexp "Xref query-replace (regexp)" ".*")))
522 (list fr 522 (list fr
523 (read-regexp (format "Xref query-replace (regexp) %s with: " fr))))) 523 (read-regexp (format "Xref query-replace (regexp) %s with: " fr)))))
524 (let ((reporter (make-progress-reporter (format "Saving search results...") 524 (let* (item xrefs iter)
525 0 (line-number-at-pos (point-max)))) 525 (save-excursion
526 (counter 0) 526 (while (setq item (xref--search-property 'xref-item))
527 pairs item) 527 (when (xref-match-length item)
528 (push item xrefs))))
528 (unwind-protect 529 (unwind-protect
529 (progn 530 (progn
530 (save-excursion 531 (goto-char (point-min))
531 (goto-char (point-min)) 532 (setq iter (xref--buf-pairs-iterator (nreverse xrefs)))
532 ;; TODO: This list should be computed on-demand instead. 533 (xref--query-replace-1 from to iter))
533 ;; As long as the UI just iterates through matches one by 534 (funcall iter :cleanup))))
534 ;; one, there's no need to compute them all in advance. 535
535 ;; Then we can throw away the reporter. 536(defun xref--buf-pairs-iterator (xrefs)
536 (while (setq item (xref--search-property 'xref-item)) 537 (let (chunk-done item next-pair file-buf pairs all-pairs)
537 (when (xref-match-length item) 538 (lambda (action)
538 (save-excursion 539 (pcase action
539 (let* ((loc (xref-item-location item)) 540 (:next
540 (beg (xref-location-marker loc)) 541 (when (or xrefs next-pair)
541 (end (move-marker (make-marker) 542 (setq chunk-done nil)
542 (+ beg (xref-match-length item)) 543 (when next-pair
543 (marker-buffer beg)))) 544 (setq file-buf (marker-buffer (car next-pair))
544 ;; Perform sanity check first. 545 pairs (list next-pair)
545 (xref--goto-location loc) 546 next-pair nil))
546 ;; FIXME: The check should probably be a generic 547 (while (and (not chunk-done)
547 ;; function, instead of the assumption that all 548 (setq item (pop xrefs)))
548 ;; matches contain the full line as summary. 549 (save-excursion
549 ;; TODO: Offer to re-scan otherwise. 550 (let* ((loc (xref-item-location item))
550 (unless (equal (buffer-substring-no-properties 551 (beg (xref-location-marker loc))
551 (line-beginning-position) 552 (end (move-marker (make-marker)
552 (line-end-position)) 553 (+ beg (xref-match-length item))
553 (xref-item-summary item)) 554 (marker-buffer beg))))
554 (user-error "Search results out of date")) 555 (let ((pair (cons beg end)))
555 (progress-reporter-update reporter (cl-incf counter)) 556 (push pair all-pairs)
556 (push (cons beg end) pairs))))) 557 ;; Perform sanity check first.
557 (setq pairs (nreverse pairs))) 558 (xref--goto-location loc)
558 (unless pairs (user-error "No suitable matches here")) 559 (if (xref--outdated-p item
559 (progress-reporter-done reporter) 560 (buffer-substring-no-properties
560 (xref--query-replace-1 from to pairs)) 561 (line-beginning-position)
561 (dolist (pair pairs) 562 (line-end-position)))
562 (move-marker (car pair) nil) 563 (message "Search result out of date, skipping")
563 (move-marker (cdr pair) nil))))) 564 (cond
565 ((null file-buf)
566 (setq file-buf (marker-buffer beg))
567 (push pair pairs))
568 ((equal file-buf (marker-buffer beg))
569 (push pair pairs))
570 (t
571 (setq chunk-done t
572 next-pair pair))))))))
573 (cons file-buf (nreverse pairs))))
574 (:cleanup
575 (dolist (pair all-pairs)
576 (move-marker (car pair) nil)
577 (move-marker (cdr pair) nil)))))))
578
579(defun xref--outdated-p (item line-text)
580 ;; FIXME: The check should probably be a generic function instead of
581 ;; the assumption that all matches contain the full line as summary.
582 (let ((summary (xref-item-summary item))
583 (strip (lambda (s) (if (string-match "\r\\'" s)
584 (substring-no-properties s 0 -1)
585 s))))
586 (not
587 ;; Sometimes buffer contents include ^M, and sometimes Grep
588 ;; output includes it, and they don't always match.
589 (equal (funcall strip line-text)
590 (funcall strip summary)))))
564 591
565;; FIXME: Write a nicer UI. 592;; FIXME: Write a nicer UI.
566(defun xref--query-replace-1 (from to pairs) 593(defun xref--query-replace-1 (from to iter)
567 (let* ((query-replace-lazy-highlight nil) 594 (let* ((query-replace-lazy-highlight nil)
568 current-beg current-end current-buf 595 (continue t)
596 did-it-once buf-pairs pairs
597 current-beg current-end
569 ;; Counteract the "do the next match now" hack in 598 ;; Counteract the "do the next match now" hack in
570 ;; `perform-replace'. And still, it'll report that those 599 ;; `perform-replace'. And still, it'll report that those
571 ;; matches were "filtered out" at the end. 600 ;; matches were "filtered out" at the end.
572 (isearch-filter-predicate 601 (isearch-filter-predicate
573 (lambda (beg end) 602 (lambda (beg end)
574 (and current-beg 603 (and current-beg
575 (eq (current-buffer) current-buf)
576 (>= beg current-beg) 604 (>= beg current-beg)
577 (<= end current-end)))) 605 (<= end current-end))))
578 (replace-re-search-function 606 (replace-re-search-function
@@ -581,19 +609,22 @@ references displayed in the current *xref* buffer."
581 (while (and (not found) pairs) 609 (while (and (not found) pairs)
582 (setq pair (pop pairs) 610 (setq pair (pop pairs)
583 current-beg (car pair) 611 current-beg (car pair)
584 current-end (cdr pair) 612 current-end (cdr pair))
585 current-buf (marker-buffer current-beg))
586 (xref--with-dedicated-window
587 (pop-to-buffer current-buf))
588 (goto-char current-beg) 613 (goto-char current-beg)
589 (when (re-search-forward from current-end noerror) 614 (when (re-search-forward from current-end noerror)
590 (setq found t))) 615 (setq found t)))
591 found)))) 616 found))))
592 ;; FIXME: Despite this being a multi-buffer replacement, `N' 617 (while (and continue (setq buf-pairs (funcall iter :next)))
593 ;; doesn't work, because we're not using 618 (if did-it-once
594 ;; `multi-query-replace-map', and it would expect the below 619 ;; Reuse the same window for subsequent buffers.
595 ;; function to be called once per buffer. 620 (switch-to-buffer (car buf-pairs))
596 (perform-replace from to t t nil))) 621 (xref--with-dedicated-window
622 (pop-to-buffer (car buf-pairs)))
623 (setq did-it-once t))
624 (setq pairs (cdr buf-pairs))
625 (setq continue
626 (perform-replace from to t t nil nil multi-query-replace-map)))
627 (unless did-it-once (user-error "No suitable matches here"))))
597 628
598(defvar xref--xref-buffer-mode-map 629(defvar xref--xref-buffer-mode-map
599 (let ((map (make-sparse-keymap))) 630 (let ((map (make-sparse-keymap)))
@@ -687,7 +718,9 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)."
687(defun xref--show-xref-buffer (xrefs alist) 718(defun xref--show-xref-buffer (xrefs alist)
688 (let ((xref-alist (xref--analyze xrefs))) 719 (let ((xref-alist (xref--analyze xrefs)))
689 (with-current-buffer (get-buffer-create xref-buffer-name) 720 (with-current-buffer (get-buffer-create xref-buffer-name)
690 (let ((inhibit-read-only t)) 721 (setq buffer-undo-list nil)
722 (let ((inhibit-read-only t)
723 (buffer-undo-list t))
691 (erase-buffer) 724 (erase-buffer)
692 (xref--insert-xrefs xref-alist) 725 (xref--insert-xrefs xref-alist)
693 (xref--xref-buffer-mode) 726 (xref--xref-buffer-mode)
@@ -908,6 +941,8 @@ IGNORES is a list of glob patterns."
908 (require 'find-dired) ; for `find-name-arg' 941 (require 'find-dired) ; for `find-name-arg'
909 (defvar grep-find-template) 942 (defvar grep-find-template)
910 (defvar find-name-arg) 943 (defvar find-name-arg)
944 ;; `shell-quote-argument' quotes the tilde as well.
945 (cl-assert (not (string-match-p "\\`~" dir)))
911 (grep-expand-template 946 (grep-expand-template
912 grep-find-template 947 grep-find-template
913 regexp 948 regexp
@@ -919,14 +954,13 @@ IGNORES is a list of glob patterns."
919 (concat " -o " find-name-arg " ")) 954 (concat " -o " find-name-arg " "))
920 " " 955 " "
921 (shell-quote-argument ")")) 956 (shell-quote-argument ")"))
922 dir 957 (shell-quote-argument dir)
923 (xref--find-ignores-arguments ignores dir))) 958 (xref--find-ignores-arguments ignores dir)))
924 959
925(defun xref--find-ignores-arguments (ignores dir) 960(defun xref--find-ignores-arguments (ignores dir)
926 "Convert IGNORES and DIR to a list of arguments for 'find'. 961 "Convert IGNORES and DIR to a list of arguments for 'find'.
927IGNORES is a list of glob patterns. DIR is an absolute 962IGNORES is a list of glob patterns. DIR is an absolute
928directory, used as the root of the ignore globs." 963directory, used as the root of the ignore globs."
929 ;; `shell-quote-argument' quotes the tilde as well.
930 (cl-assert (not (string-match-p "\\`~" dir))) 964 (cl-assert (not (string-match-p "\\`~" dir)))
931 (when ignores 965 (when ignores
932 (concat 966 (concat
@@ -1014,7 +1048,11 @@ directory, used as the root of the ignore globs."
1014 (syntax-propertize line-end) 1048 (syntax-propertize line-end)
1015 ;; FIXME: This results in several lines with the same 1049 ;; FIXME: This results in several lines with the same
1016 ;; summary. Solve with composite pattern? 1050 ;; summary. Solve with composite pattern?
1017 (while (re-search-forward regexp line-end t) 1051 (while (and
1052 ;; REGEXP might match an empty string. Or line.
1053 (or (null matches)
1054 (> (point) line-beg))
1055 (re-search-forward regexp line-end t))
1018 (let* ((beg-column (- (match-beginning 0) line-beg)) 1056 (let* ((beg-column (- (match-beginning 0) line-beg))
1019 (end-column (- (match-end 0) line-beg)) 1057 (end-column (- (match-end 0) line-beg))
1020 (loc (xref-make-file-location file line beg-column)) 1058 (loc (xref-make-file-location file line beg-column))
diff --git a/lisp/replace.el b/lisp/replace.el
index 169fc3f4701..0b25200be57 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -191,18 +191,15 @@ wants to replace FROM with TO."
191 ;; a region in order to specify the minibuffer input. 191 ;; a region in order to specify the minibuffer input.
192 ;; That should not clobber the region for the query-replace itself. 192 ;; That should not clobber the region for the query-replace itself.
193 (save-excursion 193 (save-excursion
194 ;; The `with-current-buffer' ensures that the binding 194 (minibuffer-with-setup-hook
195 ;; for `text-property-default-nonsticky' isn't a buffer 195 (lambda ()
196 ;; local binding in the current buffer, which 196 (setq-local text-property-default-nonsticky
197 ;; `read-from-minibuffer' wouldn't see. 197 (cons '(separator . t) text-property-default-nonsticky)))
198 (with-current-buffer (window-buffer (minibuffer-window)) 198 (if regexp-flag
199 (let ((text-property-default-nonsticky 199 (read-regexp prompt nil 'query-replace-from-to-history)
200 (cons '(separator . t) text-property-default-nonsticky))) 200 (read-from-minibuffer
201 (if regexp-flag 201 prompt nil nil nil 'query-replace-from-to-history
202 (read-regexp prompt nil 'query-replace-from-to-history) 202 (car (if regexp-flag regexp-search-ring search-ring)) t)))))
203 (read-from-minibuffer
204 prompt nil nil nil 'query-replace-from-to-history
205 (car (if regexp-flag regexp-search-ring search-ring)) t))))))
206 (to)) 203 (to))
207 (if (and (zerop (length from)) query-replace-defaults) 204 (if (and (zerop (length from)) query-replace-defaults)
208 (cons (caar query-replace-defaults) 205 (cons (caar query-replace-defaults)
diff --git a/lisp/subr.el b/lisp/subr.el
index f67f70f85c9..094710b026c 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -291,21 +291,27 @@ This function accepts any number of arguments, but ignores them."
291 291
292;; Signal a compile-error if the first arg is missing. 292;; Signal a compile-error if the first arg is missing.
293(defun error (&rest args) 293(defun error (&rest args)
294 "Signal an error, making error message by passing all args to `format'. 294 "Signal an error, making a message by passing args to `format-message'.
295In Emacs, the convention is that error messages start with a capital 295In Emacs, the convention is that error messages start with a capital
296letter but *do not* end with a period. Please follow this convention 296letter but *do not* end with a period. Please follow this convention
297for the sake of consistency." 297for the sake of consistency.
298
299Note: (error \"%s\" VALUE) makes the message VALUE without
300interpreting format characters like `%', `\\=`', and `\\=''."
298 (declare (advertised-calling-convention (string &rest args) "23.1")) 301 (declare (advertised-calling-convention (string &rest args) "23.1"))
299 (signal 'error (list (apply #'format-message args)))) 302 (signal 'error (list (apply #'format-message args))))
300 303
301(defun user-error (format &rest args) 304(defun user-error (format &rest args)
302 "Signal a pilot error, making error message by passing all args to `format'. 305 "Signal a pilot error, making a message by passing args to `format-message'.
303In Emacs, the convention is that error messages start with a capital 306In Emacs, the convention is that error messages start with a capital
304letter but *do not* end with a period. Please follow this convention 307letter but *do not* end with a period. Please follow this convention
305for the sake of consistency. 308for the sake of consistency.
306This is just like `error' except that `user-error's are expected to be the 309This is just like `error' except that `user-error's are expected to be the
307result of an incorrect manipulation on the part of the user, rather than the 310result of an incorrect manipulation on the part of the user, rather than the
308result of an actual problem." 311result of an actual problem.
312
313Note: (user-error \"%s\" VALUE) makes the message VALUE without
314interpreting format characters like `%', `\\=`', and `\\=''."
309 (signal 'user-error (list (apply #'format-message format args)))) 315 (signal 'user-error (list (apply #'format-message format args))))
310 316
311(defun define-error (name message &optional parent) 317(defun define-error (name message &optional parent)
@@ -1123,6 +1129,7 @@ The return value is a positive integer."
1123 1129
1124(defun posnp (obj) 1130(defun posnp (obj)
1125 "Return non-nil if OBJ appears to be a valid `posn' object specifying a window. 1131 "Return non-nil if OBJ appears to be a valid `posn' object specifying a window.
1132A `posn' object is returned from functions such as `event-start'.
1126If OBJ is a valid `posn' object, but specifies a frame rather 1133If OBJ is a valid `posn' object, but specifies a frame rather
1127than a window, return nil." 1134than a window, return nil."
1128 ;; FIXME: Correct the behavior of this function so that all valid 1135 ;; FIXME: Correct the behavior of this function so that all valid
diff --git a/src/bidi.c b/src/bidi.c
index c23ff954356..573e513469d 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -2498,10 +2498,10 @@ typedef struct bpa_stack_entry {
2498 2498
2499 And finally, cross-reference these two: 2499 And finally, cross-reference these two:
2500 2500
2501 fgrep -w -f brackets.txt decompositions.txt 2501 grep -Fw -f brackets.txt decompositions.txt
2502 2502
2503 where "decompositions.txt" was produced by the 1st script, and 2503 where "decompositions.txt" was produced by the 1st script, and
2504 "brackets.txt" by the 2nd script. In the output of fgrep, look 2504 "brackets.txt" by the 2nd script. In the output of grep, look
2505 only for decompositions that don't begin with some compatibility 2505 only for decompositions that don't begin with some compatibility
2506 formatting tag, such as "<compat>". Only decompositions that 2506 formatting tag, such as "<compat>". Only decompositions that
2507 consist solely of character codepoints are relevant to bidi 2507 consist solely of character codepoints are relevant to bidi
diff --git a/src/callint.c b/src/callint.c
index e56f7cd1b84..053ee6cdaa5 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -272,7 +272,7 @@ invoke it. If KEYS is omitted or nil, the return value of
272{ 272{
273 /* `args' will contain the array of arguments to pass to the function. 273 /* `args' will contain the array of arguments to pass to the function.
274 `visargs' will contain the same list but in a nicer form, so that if we 274 `visargs' will contain the same list but in a nicer form, so that if we
275 pass it to `Fformat' it will be understandable to a human. */ 275 pass it to `Fformat_message' it will be understandable to a human. */
276 Lisp_Object *args, *visargs; 276 Lisp_Object *args, *visargs;
277 Lisp_Object specs; 277 Lisp_Object specs;
278 Lisp_Object filter_specs; 278 Lisp_Object filter_specs;
diff --git a/src/doprnt.c b/src/doprnt.c
index 506bbc3df35..9d8b783565f 100644
--- a/src/doprnt.c
+++ b/src/doprnt.c
@@ -46,15 +46,15 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
46 ignored %s and %c conversions. (See below for the detailed documentation of 46 ignored %s and %c conversions. (See below for the detailed documentation of
47 what is supported.) However, this is okay, as this function is supposed to 47 what is supported.) However, this is okay, as this function is supposed to
48 be called from `error' and similar functions, and thus does not need to 48 be called from `error' and similar functions, and thus does not need to
49 support features beyond those in `Fformat', which is used by `error' on the 49 support features beyond those in `Fformat_message', which is used
50 Lisp level. */ 50 by `error' on the Lisp level. */
51 51
52/* In the FORMAT argument this function supports ` and ' as directives 52/* In the FORMAT argument this function supports ` and ' as directives
53 that output left and right quotes as per ‘text-quoting style’. It 53 that output left and right quotes as per ‘text-quoting style’. It
54 also supports the following %-sequences: 54 also supports the following %-sequences:
55 55
56 %s means print a string argument. 56 %s means print a string argument.
57 %S is silently treated as %s, for loose compatibility with `Fformat'. 57 %S is treated as %s, for loose compatibility with `Fformat_message'.
58 %d means print a `signed int' argument in decimal. 58 %d means print a `signed int' argument in decimal.
59 %o means print an `unsigned int' argument in octal. 59 %o means print an `unsigned int' argument in octal.
60 %x means print an `unsigned int' argument in hex. 60 %x means print an `unsigned int' argument in hex.
diff --git a/src/editfns.c b/src/editfns.c
index 11a82c3da73..0e1a6e3415f 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -3716,10 +3716,11 @@ In batch mode, the message is printed to the standard error stream,
3716followed by a newline. 3716followed by a newline.
3717 3717
3718The first argument is a format control string, and the rest are data 3718The first argument is a format control string, and the rest are data
3719to be formatted under control of the string. See `format' for details. 3719to be formatted under control of the string. See `format-message' for
3720details.
3720 3721
3721Note: Use (message "%s" VALUE) to print the value of expressions and 3722Note: (message "%s" VALUE) displays the string VALUE without
3722variables to avoid accidentally interpreting `%' as format specifiers. 3723interpreting format characters like `%', `\\=`', and `\\=''.
3723 3724
3724If the first argument is nil or the empty string, the function clears 3725If the first argument is nil or the empty string, the function clears
3725any existing message; this lets the minibuffer contents show. See 3726any existing message; this lets the minibuffer contents show. See
@@ -3747,7 +3748,8 @@ DEFUN ("message-box", Fmessage_box, Smessage_box, 1, MANY, 0,
3747 doc: /* Display a message, in a dialog box if possible. 3748 doc: /* Display a message, in a dialog box if possible.
3748If a dialog box is not available, use the echo area. 3749If a dialog box is not available, use the echo area.
3749The first argument is a format control string, and the rest are data 3750The first argument is a format control string, and the rest are data
3750to be formatted under control of the string. See `format' for details. 3751to be formatted under control of the string. See `format-message' for
3752details.
3751 3753
3752If the first argument is nil or the empty string, clear any existing 3754If the first argument is nil or the empty string, clear any existing
3753message; let the minibuffer contents show. 3755message; let the minibuffer contents show.
@@ -3778,7 +3780,8 @@ If this command was invoked with the mouse, use a dialog box if
3778`use-dialog-box' is non-nil. 3780`use-dialog-box' is non-nil.
3779Otherwise, use the echo area. 3781Otherwise, use the echo area.
3780The first argument is a format control string, and the rest are data 3782The first argument is a format control string, and the rest are data
3781to be formatted under control of the string. See `format' for details. 3783to be formatted under control of the string. See `format-message' for
3784details.
3782 3785
3783If the first argument is nil or the empty string, clear any existing 3786If the first argument is nil or the empty string, clear any existing
3784message; let the minibuffer contents show. 3787message; let the minibuffer contents show.
diff --git a/test/automated/data/xref/file1.txt b/test/automated/data/xref/file1.txt
new file mode 100644
index 00000000000..5d7cc544443
--- /dev/null
+++ b/test/automated/data/xref/file1.txt
@@ -0,0 +1,2 @@
1foo foo
2bar
diff --git a/test/automated/data/xref/file2.txt b/test/automated/data/xref/file2.txt
new file mode 100644
index 00000000000..9f075f26004
--- /dev/null
+++ b/test/automated/data/xref/file2.txt
@@ -0,0 +1,2 @@
1
2bar
diff --git a/test/automated/xref-tests.el b/test/automated/xref-tests.el
new file mode 100644
index 00000000000..079b196aa8b
--- /dev/null
+++ b/test/automated/xref-tests.el
@@ -0,0 +1,91 @@
1;;; xref-tests.el --- tests for xref
2
3;; Copyright (C) 2016 Free Software Foundation, Inc.
4
5;; Author: Dmitry Gutov <dgutov@yandex.ru>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21
22;;; Commentary:
23
24;;; Code:
25
26(require 'xref)
27(require 'cl-lib)
28
29(defvar xref-tests-data-dir
30 (expand-file-name "data/xref/"
31 (file-name-directory (or load-file-name (buffer-file-name)))))
32
33(ert-deftest xref-collect-matches-finds-none-for-some-regexp ()
34 (should (null (xref-collect-matches "zzz" "*" xref-tests-data-dir nil))))
35
36(ert-deftest xref-collect-matches-finds-some-for-bar ()
37 (let* ((matches (xref-collect-matches "bar" "*" xref-tests-data-dir nil))
38 (locs (cl-sort (mapcar #'xref-item-location matches)
39 #'string<
40 :key #'xref-location-group)))
41 (should (= 2 (length matches)))
42 (should (string-match-p "file1\\.txt\\'" (xref-location-group (nth 0 locs))))
43 (should (string-match-p "file2\\.txt\\'" (xref-location-group (nth 1 locs))))))
44
45(ert-deftest xref-collect-matches-finds-two-matches-on-the-same-line ()
46 (let* ((matches (xref-collect-matches "foo" "*" xref-tests-data-dir nil))
47 (locs (mapcar #'xref-item-location matches)))
48 (should (= 2 (length matches)))
49 (should (string-match-p "file1\\.txt\\'" (xref-location-group (nth 0 locs))))
50 (should (string-match-p "file1\\.txt\\'" (xref-location-group (nth 1 locs))))
51 (should (equal 1 (xref-location-line (nth 0 locs))))
52 (should (equal 1 (xref-location-line (nth 1 locs))))
53 (should (equal 0 (xref-file-location-column (nth 0 locs))))
54 (should (equal 4 (xref-file-location-column (nth 1 locs))))))
55
56(ert-deftest xref-collect-matches-finds-an-empty-line-regexp-match ()
57 (let* ((matches (xref-collect-matches "^$" "*" xref-tests-data-dir nil))
58 (locs (mapcar #'xref-item-location matches)))
59 (should (= 1 (length matches)))
60 (should (string-match-p "file2\\.txt\\'" (xref-location-group (nth 0 locs))))
61 (should (equal 1 (xref-location-line (nth 0 locs))))
62 (should (equal 0 (xref-file-location-column (nth 0 locs))))))
63
64(ert-deftest xref--buf-pairs-iterator-groups-markers-by-buffers-1 ()
65 (let* ((xrefs (xref-collect-matches "foo" "*" xref-tests-data-dir nil))
66 (iter (xref--buf-pairs-iterator xrefs))
67 (cons (funcall iter :next)))
68 (should (null (funcall iter :next)))
69 (should (string-match "file1\\.txt\\'" (buffer-file-name (car cons))))
70 (should (= 2 (length (cdr cons))))))
71
72(ert-deftest xref--buf-pairs-iterator-groups-markers-by-buffers-2 ()
73 (let* ((xrefs (xref-collect-matches "bar" "*" xref-tests-data-dir nil))
74 (iter (xref--buf-pairs-iterator xrefs))
75 (cons1 (funcall iter :next))
76 (cons2 (funcall iter :next)))
77 (should (null (funcall iter :next)))
78 (should-not (equal (car cons1) (car cons2)))
79 (should (= 1 (length (cdr cons1))))
80 (should (= 1 (length (cdr cons2))))))
81
82(ert-deftest xref--buf-pairs-iterator-cleans-up-markers ()
83 (let* ((xrefs (xref-collect-matches "bar" "*" xref-tests-data-dir nil))
84 (iter (xref--buf-pairs-iterator xrefs))
85 (cons1 (funcall iter :next))
86 (cons2 (funcall iter :next)))
87 (funcall iter :cleanup)
88 (should (null (marker-position (car (nth 0 (cdr cons1))))))
89 (should (null (marker-position (cdr (nth 0 (cdr cons1))))))
90 (should (null (marker-position (car (nth 0 (cdr cons2))))))
91 (should (null (marker-position (cdr (nth 0 (cdr cons2))))))))