emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 11b2744 1/5: substitute-command-keys now curves quo


From: Paul Eggert
Subject: [Emacs-diffs] master 11b2744 1/5: substitute-command-keys now curves quotes
Date: Thu, 28 May 2015 07:22:10 +0000

branch: master
commit 11b2744f48fc03f1511de1152ad49807557c6f85
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    substitute-command-keys now curves quotes
    
    So, for example, it turns "`abc'" into "‘abc’" (Bug#20385).
    * doc/lispref/help.texi (Keys in Documentation):
    * etc/NEWS: Document this.
    * src/doc.c (Fsubstitute_command_keys): Implement it.
---
 doc/lispref/help.texi |   22 +++++++++++++++-------
 etc/NEWS              |    6 ++++++
 src/doc.c             |   39 +++++++++++++++++++++++++++++++++------
 3 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi
index 868d284..ce29f3f 100644
--- a/doc/lispref/help.texi
+++ b/doc/lispref/help.texi
@@ -318,10 +318,18 @@ stands for no text itself.  It is used only for a side 
effect: it
 specifies @var{mapvar}'s value as the keymap for any following
 @address@hidden sequences in this documentation string.
 
address@hidden `
+(grave accent) stands for a left single quotation mark (@samp{‘}).
+
address@hidden '
+(apostrophe) stands for a right single quotation mark (@samp{’}) if
+preceded by grave accent and there are no intervening apostrophes.
+Otherwise, apostrophe stands for itself.
+
 @item \=
-quotes the following character and is discarded; thus, @samp{\=\[} puts
address@hidden into the output, and @samp{\=\=} puts @samp{\=} into the
-output.
+quotes the following character and is discarded; thus, @samp{\=`} puts
address@hidden into the output, @samp{\=\[} puts @samp{\[} into the output,
+and @samp{\=\=} puts @samp{\=} into the output.
 @end table
 
 @strong{Please note:} Each @samp{\} must be doubled when written in a
@@ -354,8 +362,8 @@ specifies a key binding that the command does not actually 
have.
 @smallexample
 @group
 (substitute-command-keys
-   "To abort recursive edit, type: \\[abort-recursive-edit]")
address@hidden "To abort recursive edit, type: C-]"
+   "To abort recursive edit, type ‘\\[abort-recursive-edit]’.")
address@hidden "To abort recursive edit, type ‘C-]’."
 @end group
 
 @group
@@ -376,8 +384,8 @@ C-g             abort-recursive-edit
 @group
 (substitute-command-keys
    "To abort a recursive edit from the minibuffer, type\
-\\<minibuffer-local-must-match-map>\\[abort-recursive-edit].")
address@hidden "To abort a recursive edit from the minibuffer, type C-g."
+`\\<minibuffer-local-must-match-map>\\[abort-recursive-edit]'.")
address@hidden "To abort a recursive edit from the minibuffer, type ‘C-g’."
 @end group
 @end smallexample
 
diff --git a/etc/NEWS b/etc/NEWS
index a220330..5afd40e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -805,6 +805,12 @@ when signaling a file error.  For example, it now reports 
"Permission
 denied" instead of "permission denied".  The old behavior was problematic
 in languages like German where downcasing rules depend on grammar.
 
+** (substitute-command-keys "`foo'") now returns "‘foo’".
+That is, it replaces grave accents by left single quotation marks, and
+apostrophes that match grave accents by right single quotation marks.
+As before, isolated apostrophes and characters preceded by \= are
+output as-is.
+
 +++
 ** The character classes [:alpha:] and [:alnum:] in regular expressions
 now match multibyte characters using Unicode character properties.
diff --git a/src/doc.c b/src/doc.c
index 8b18fb0..32d6556 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -693,15 +693,21 @@ summary).
 
 Each substring of the form \\=\\<MAPVAR> specifies the use of MAPVAR
 as the keymap for future \\=\\[COMMAND] substrings.
-\\=\\= quotes the following character and is discarded;
-thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ 
into the output.
+
+Each \\=` is replaced by ‘.  Each ' preceded by \\=` and without
+intervening ' is replaced by ’.
+
+\\=\\= quotes the following character and is discarded; thus,
+\\=\\=\\=\\= puts \\=\\= into the output, \\=\\=\\=\\[ puts \\=\\[ into the 
output, and
+\\=\\=\\=` puts \\=` into the output.
 
 Return the original STRING if no substitutions are made.
 Otherwise, return a new string.  */)
   (Lisp_Object string)
 {
   char *buf;
-  bool changed = 0;
+  bool changed = false;
+  bool in_quote = false;
   unsigned char *strp;
   char *bufp;
   ptrdiff_t idx;
@@ -734,6 +740,12 @@ Otherwise, return a new string.  */)
   keymap = Voverriding_local_map;
 
   bsize = SBYTES (string);
+
+  /* Add some room for expansion due to quote replacement.  */
+  enum { EXTRA_ROOM = 20 };
+  if (bsize <= STRING_BYTES_BOUND - EXTRA_ROOM)
+    bsize += EXTRA_ROOM;
+
   bufp = buf = xmalloc (bsize);
 
   strp = SDATA (string);
@@ -743,7 +755,7 @@ Otherwise, return a new string.  */)
        {
          /* \= quotes the next character;
             thus, to put in \[ without its special meaning, use \=\[.  */
-         changed = 1;
+         changed = true;
          strp += 2;
          if (multibyte)
            {
@@ -766,7 +778,6 @@ Otherwise, return a new string.  */)
          ptrdiff_t start_idx;
          bool follow_remap = 1;
 
-         changed = 1;
          strp += 2;            /* skip \[ */
          start = strp;
          start_idx = start - SDATA (string);
@@ -833,7 +844,6 @@ Otherwise, return a new string.  */)
          Lisp_Object earlier_maps;
          ptrdiff_t count = SPECPDL_INDEX ();
 
-         changed = 1;
          strp += 2;            /* skip \{ or \< */
          start = strp;
          start_idx = start - SDATA (string);
@@ -903,6 +913,7 @@ Otherwise, return a new string.  */)
          length = SCHARS (tem);
          length_byte = SBYTES (tem);
        subst:
+         changed = true;
          {
            ptrdiff_t offset = bufp - buf;
            if (STRING_BYTES_BOUND - length_byte < bsize)
@@ -916,6 +927,22 @@ Otherwise, return a new string.  */)
            strp = SDATA (string) + idx;
          }
        }
+      else if (strp[0] == '`')
+       {
+         in_quote = true;
+         start = (unsigned char *) "\xE2\x80\x98"; /* ‘ */
+       subst_quote:
+         length = 1;
+         length_byte = 3;
+         idx = strp - SDATA (string) + 1;
+         goto subst;
+       }
+      else if (strp[0] == '\'' && in_quote)
+       {
+         in_quote = false;
+         start = (unsigned char *) "\xE2\x80\x99"; /* ’ */
+         goto subst_quote;
+       }
       else if (! multibyte)            /* just copy other chars */
        *bufp++ = *strp++, nchars++;
       else



reply via email to

[Prev in Thread] Current Thread [Next in Thread]