summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2015-05-28 00:06:13 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2015-05-28 00:22:01 -0700
commit11b2744f48fc03f1511de1152ad49807557c6f85 (patch)
tree319aded310f155b109149157f6c075138205fbe5
parent2363d498fb99bda0b5030c8c1af2925209bb60e5 (diff)
downloademacs-11b2744f48fc03f1511de1152ad49807557c6f85.tar.gz
emacs-11b2744f48fc03f1511de1152ad49807557c6f85.tar.bz2
emacs-11b2744f48fc03f1511de1152ad49807557c6f85.zip
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.
-rw-r--r--doc/lispref/help.texi22
-rw-r--r--etc/NEWS6
-rw-r--r--src/doc.c39
3 files changed, 54 insertions, 13 deletions
diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi
index 868d2843569..ce29f3f5bc3 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
@samp{\[@var{command}]} sequences in this documentation string.
+@item `
+(grave accent) stands for a left single quotation mark (@samp{‘}).
+
+@item '
+(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
-@samp{\[} into the output, and @samp{\=\=} puts @samp{\=} into the
-output.
+quotes the following character and is discarded; thus, @samp{\=`} puts
+@samp{`} 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]")
-@result{} "To abort recursive edit, type: C-]"
+ "To abort recursive edit, type ‘\\[abort-recursive-edit]’.")
+@result{} "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].")
-@result{} "To abort a recursive edit from the minibuffer, type C-g."
+`\\<minibuffer-local-must-match-map>\\[abort-recursive-edit]'.")
+@result{} "To abort a recursive edit from the minibuffer, type ‘C-g’."
@end group
@end smallexample
diff --git a/etc/NEWS b/etc/NEWS
index a220330ebbf..5afd40e6727 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 8b18fb0a5a2..32d65563fd9 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