Subject: bug#21588: 25.0.50: Single quotes becoming curvy quotes in message function

From: Paul Eggert <[email-masked]>
Date: Thu, 1 Oct 2015 23:51:08 -0700

On 09/30/2015 08:54 PM, Kaushal Modi wrote:
 > - Can the default be changed to 'grave?

The GNU coding standards were changed a while ago to recommend against grave 
quoting in diagnostics and many GNU applications have already changed (e.g., 
coreutils, GCC).  Although Emacs has been one of the holdouts, now is as good a 
time as any to make the move.

> we need to update the documentation that warns the user to use the correct style.

Thanks, done in the attached patch, which I just installed in the master branch.

 > it is mentioned that typewriter quotes are simple and portable.

That discussion was intended to be about text files, so I added a phrase to that 
effect in the attached patch.  This should help resolve the seeming contradiction.

> If we want to keep the default of text-quoting-style as nil (or 'curve), more logic needs to be added that decides whether left curly quote or right curly quote should be used, which might have some performance impact as we then need to check what the previous character is, what the next character is, etc to decide if the current apostrophe needs to be replaced with a left or a right quote.

It’s not a significant performance impact.  It’s more a hassle of documenting a 
more-complex approach.  That is partly why I gave up on such an approach after 
implementing it, and went with the simpler approach that is in Emacs master now.

 > CASE 1: 'Hey' -> ‘Hey’
 > CASE 2: it's awesome -> it’s awesome
 > CASE 3: my sisters' weddings -> my sisters’ weddings
 > CASE 4: He said 'It's awesome!' -> He said ‘It’s awesome!’

‘message’ already does cases 2 and 3 that way, as well as the 2nd apostrophe in 
case 4.  The remaining cases are quite rare in Emacs diagnostics, as the Emacs 
style uses directed quotes when single-quoting.

> If there's a non-space character before the apostrophe, replace it with right quote, else use left quote.

That would mishandle common English phrases like “'60s pop culture” and “rock 
'n' roll”.  (These phrases don’t occur in Emacs diagnostics either, but as long 
as we’re being pedantic....)  Any heuristics will go awry sometimes so we need 
some way to override the heuristics; and once we have such an override, there is 
a real benefit to keeping the heuristics simple.
From dd6346e00c0910b16f1bd195e5e94f6ac1d696ee Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Thu, 1 Oct 2015 21:42:53 -0700
Subject: [PATCH] Fix a few problems with directed quotes

This is in response to a problem report by Kaushal Modi in:
http://bugs.gnu.org/21588#25
* lisp/cedet/mode-local.el (describe-mode-local-overload):
* lisp/emacs-lisp/bytecomp.el (byte-compile-fix-header):
* lisp/info-xref.el (info-xref-check-all-custom):
* lisp/mail/emacsbug.el (report-emacs-bug-hook):
Prefer directed to undirected single quotes in diagnostics.
---
 doc/emacs/text.texi         |  4 ++--
 doc/lispref/control.texi    | 16 +++++++++++-----
 doc/lispref/display.texi    | 22 ++++++++++++++++------
 lisp/cedet/mode-local.el    |  4 ++--
 lisp/emacs-lisp/bytecomp.el |  2 +-
 lisp/emacs-lisp/elint.el    |  2 +-
 lisp/info-xref.el           |  2 +-
 lisp/mail/emacsbug.el       |  3 ++-
 lisp/mh-e/mh-e.el           |  4 ++--
 lisp/net/newst-treeview.el  |  2 +-
 10 files changed, 39 insertions(+), 22 deletions(-)

diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi
index 7f3afd7..bab660e 100644
--- a/doc/emacs/text.texi
+++ b/doc/emacs/text.texi
@@ -417,8 +417,8 @@ beginning of a line.
 using straight apostrophes @t{'like this'} or double-quotes @t{"like
 this"}.  Another common way is the curved quote convention, which uses
 left and right single or double quotation marks @t{‘like this’} or
-@t{“like this”}.  Typewriter quotes are simple and portable; curved
-quotes are less ambiguous and typically look nicer.
+@t{“like this”}.  In text files, typewriter quotes are simple and
+portable; curved quotes are less ambiguous and typically look nicer.
 
   Electric Quote mode makes it easier to type curved quotes.  As you
 type characters it optionally converts @t{`} to @t{‘}, @t{'} to @t{’},
diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index fca16da..412903f 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -1,4 +1,4 @@
-@c -*-texinfo-*-
+@c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
 @c Copyright (C) 1990-1995, 1998-1999, 2001-2015 Free Software
 @c Foundation, Inc.
@@ -1002,8 +1002,8 @@ These examples show typical uses of @code{error}:
 @end group
 
 @group
-(error "You have committed %d errors" 10)
-     @error{} You have committed 10 errors
+(error "Invalid name `%s'" "A%%B")
+     @error{} Invalid name ‘A%%B’
 @end group
 @end example
 
@@ -1011,10 +1011,16 @@ These examples show typical uses of @code{error}:
 error symbol @code{error}, and a list containing the string returned by
 @code{format-message}.
 
+In a format string containing single quotes, curved quotes @t{‘like
+this’} and grave quotes @t{`like this'} work better than straight
+quotes @t{'like this'}, as @code{error} typically formats every
+straight quote as a curved closing quote.
+
 @strong{Warning:} If you want to use your own string as an error message
 verbatim, don't just write @code{(error @var{string})}.  If @var{string}
-contains @samp{%}, it will be interpreted as a format specifier, with
-undesirable results.  Instead, use @code{(error "%s" @var{string})}.
+@var{string} contains @samp{%}, @samp{`}, or @samp{'} it may be
+reformatted, with undesirable results.  Instead, use @code{(error "%s"
+@var{string})}.
 @end defun
 
 @defun signal error-symbol data
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 452462a..ad248b1 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -1,4 +1,4 @@
-@c -*-texinfo-*-
+@c -*- mode: texinfo; coding: utf-8 -*-
 @c This is part of the GNU Emacs Lisp Reference Manual.
 @c Copyright (C) 1990-1995, 1998-2015 Free Software Foundation, Inc.
 @c See the file elisp.texi for copying conditions.
@@ -254,6 +254,11 @@ properties, it is displayed with the specified faces (@pxref{Faces}).
 The string is also added to the @file{*Messages*} buffer, but without
 text properties (@pxref{Logging Messages}).
 
+In a format string containing single quotes, curved quotes @t{‘like
+this’} and grave quotes @t{`like this'} work better than straight
+quotes @t{'like this'}, as @code{message} typically formats every
+straight quote as a curved closing quote.
+
 In batch mode, the message is printed to the standard error stream,
 followed by a newline.
 
@@ -268,21 +273,26 @@ onto the screen immediately.
 
 @example
 @group
-(message "Minibuffer depth is %d."
-         (minibuffer-depth))
- @print{} Minibuffer depth is 0.
-@result{} "Minibuffer depth is 0."
+(message "Reverting `%s'..." (buffer-name))
+ @print{} Reverting ‘subr.el’...
+@result{} "Reverting ‘subr.el’..."
 @end group
 
 @group
 ---------- Echo Area ----------
-Minibuffer depth is 0.
+Reverting ‘subr.el’...
 ---------- Echo Area ----------
 @end group
 @end example
 
 To automatically display a message in the echo area or in a pop-buffer,
 depending on its size, use @code{display-message-or-buffer} (see below).
+
+@strong{Warning:} If you want to use your own string as a message
+verbatim, don't just write @code{(message @var{string})}.  If
+@var{string} contains @samp{%}, @samp{`}, or @samp{'} it may be
+reformatted, with undesirable results.  Instead, use @code{(message
+"%s" @var{string})}.
 @end defun
 
 @defvar inhibit-message
diff --git a/lisp/cedet/mode-local.el b/lisp/cedet/mode-local.el
index 8736a4f..b5995ff 100644
--- a/lisp/cedet/mode-local.el
+++ b/lisp/cedet/mode-local.el
@@ -644,9 +644,9 @@ SYMBOL is a function that can be overridden."
       (insert (overload-docstring-extension symbol) "\n\n")
       (insert (format-message "default function: `%s'\n" default))
       (if override
-	  (insert (format-message "\noverride in buffer '%s': `%s'\n"
+	  (insert (format-message "\noverride in buffer `%s': `%s'\n"
 				  describe-function-orig-buffer override))
-	(insert (format-message "\nno override in buffer '%s'\n"
+	(insert (format-message "\nno override in buffer `%s'\n"
 				describe-function-orig-buffer)))
 
       (mapatoms
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 8699af6..6f7ba33 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -2015,7 +2015,7 @@ and will be removed soon.  See (elisp)Backquote in the manual."))
        (format "     (string-lessp emacs-version \"%s\")\n" minimum-version)
        ;; Because the header must fit in a fixed width, we cannot
        ;; insert arbitrary-length file names (Bug#11585).
-       "     (error \"'%s' was compiled for "
+       "     (error \"`%s' was compiled for "
        (format "Emacs %s or later\" #$))\n\n" minimum-version))
       ;; Now compensate for any change in size, to make sure all
       ;; positions in the file remain valid.
diff --git a/lisp/emacs-lisp/elint.el b/lisp/emacs-lisp/elint.el
index 86ac33c..64d65c0 100644
--- a/lisp/emacs-lisp/elint.el
+++ b/lisp/emacs-lisp/elint.el
@@ -520,7 +520,7 @@ Return nil if there are no more forms, t otherwise."
 	      ;;; 	(with-syntax-table emacs-lisp-mode-syntax-table
 	      ;;; 	  (elint-update-env))
 	      ;;; 	(setq env (elint-env-add-env env elint-buffer-env))))
-	      ;;(message "Elint processed (require '%s)" name))
+	      ;;(message "%s" (format "Elint processed (require '%s)" name))
 	  (error "%s.el not found in load-path" libname)))
     (error
      (message "Can't get variables from require'd library %s: %s"
diff --git a/lisp/info-xref.el b/lisp/info-xref.el
index 2b81efa..fcdf532 100644
--- a/lisp/info-xref.el
+++ b/lisp/info-xref.el
@@ -454,7 +454,7 @@ and can take a long time."
         (cond ((symbolp load)
                (condition-case cause (require load)
                  (error
-                  (info-xref-output "Symbol `%s': cannot require '%s: %s"
+                  (info-xref-output "Symbol `%s': cannot require `%s': %s"
                                     symbol load cause))))
               ;; skip if previously loaded
               ((assoc load load-history))
diff --git a/lisp/mail/emacsbug.el b/lisp/mail/emacsbug.el
index f54893f..8e28973 100644
--- a/lisp/mail/emacsbug.el
+++ b/lisp/mail/emacsbug.el
@@ -417,7 +417,8 @@ and send the mail again%s."
 					 (regexp-quote (system-name)))
 				 from))
 	       (not (yes-or-no-p
-		     (format "Is '%s' really your email address? " from)))
+		     (format-message "Is `%s' really your email address? "
+                                     from)))
 	       (error "Please edit the From address and try again"))))))

diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el
index 96fe7d7..c757920 100644
--- a/lisp/mh-e/mh-e.el
+++ b/lisp/mh-e/mh-e.el
@@ -2901,11 +2901,11 @@ This option contains the Unix command line which performs the
 actual printing for the \\[mh-print-msg] command. The string can
 contain one escape, \"%s\", which is replaced by the name of the
 folder and the message number and is useful for print job names.
-I use \"mpage -h'%s' -b Letter -H1of -mlrtb -P\" which produces a
+I use \"mpage -h\\='%s\\=' -b Letter -H1of -mlrtb -P\" which produces a
 nice header and adds a bit of margin so the text fits within my
 printer's margins.
 
-This options is not used by the commands \\[mh-ps-print-msg] or
+This option is not used by the commands \\[mh-ps-print-msg] or
 \\[mh-ps-print-msg-file]."
   :type 'string
   :group 'mh-show
diff --git a/lisp/net/newst-treeview.el b/lisp/net/newst-treeview.el
index 4eef580..0c2df88 100644
--- a/lisp/net/newst-treeview.el
+++ b/lisp/net/newst-treeview.el
@@ -940,7 +940,7 @@ Optional arguments CHANGED-WIDGET and EVENT are ignored."
   "Return propertized copy of string TAG.
 Optional argument NUM-NEW is used for choosing face, other
 arguments NT-ID, FEED, and VFEED are added as properties."
-  ;;(message "newsticker--treeview-propertize-tag '%s' %s" feed nt-id)
+  ;;(message "newsticker--treeview-propertize-tag `%s' %s" feed nt-id)
   (let ((face 'newsticker-treeview-face)
         (map (make-sparse-keymap)))
     (if (and num-new (> num-new 0))
-- 
2.1.4