X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/95a2cb24b0697558e6629460d8bc693b394f0138..a246df7256ff119cc14cc9a8f8da34bf2ccc2b65:/src/doc.c diff --git a/src/doc.c b/src/doc.c index 8b18fb0a5a..78a7815aad 100644 --- a/src/doc.c +++ b/src/doc.c @@ -1,4 +1,4 @@ -/* Record indices of function doc strings stored in a file. +/* Record indices of function doc strings stored in a file. -*- coding: utf-8 -*- Copyright (C) 1985-1986, 1993-1995, 1997-2015 Free Software Foundation, Inc. @@ -32,6 +32,7 @@ along with GNU Emacs. If not, see . */ #include "lisp.h" #include "character.h" #include "buffer.h" +#include "disptab.h" #include "keyboard.h" #include "keymap.h" @@ -516,8 +517,13 @@ store_function_docstring (Lisp_Object obj, ptrdiff_t offset) if ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_DOC_STRING) ASET (fun, COMPILED_DOC_STRING, make_number (offset)); else - message ("No docstring slot for %s", - SYMBOLP (obj) ? SSDATA (SYMBOL_NAME (obj)) : ""); + { + AUTO_STRING (format, "No docstring slot for %s"); + CALLN (Fmessage, format, + (SYMBOLP (obj) + ? SYMBOL_NAME (obj) + : build_string (""))); + } } } @@ -678,6 +684,18 @@ the same file name is found in the `doc-directory'. */) return unbind_to (count, Qnil); } +/* Declare named constants for U+2018 LEFT SINGLE QUOTATION MARK and + U+2019 RIGHT SINGLE QUOTATION MARK, which have UTF-8 encodings + "\xE2\x80\x98" and "\xE2\x80\x99", respectively. */ +enum + { + LEFT_SINGLE_QUOTATION_MARK = 0x2018, + uLSQM0 = 0xE2, uLSQM1 = 0x80, uLSQM2 = 0x98, + uRSQM0 = 0xE2, uRSQM1 = 0x80, uRSQM2 = 0x99, + }; +static unsigned char const LSQM[] = { uLSQM0, uLSQM1, uLSQM2 }; +static unsigned char const RSQM[] = { uRSQM0, uRSQM1, uRSQM2 }; + DEFUN ("substitute-command-keys", Fsubstitute_command_keys, Ssubstitute_command_keys, 1, 1, 0, doc: /* Substitute key descriptions for command names in STRING. @@ -693,22 +711,30 @@ summary). Each substring of the form \\=\\ 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 \\=‘ and \\=’ are replaced by left and right quote. Each \\=` is +replaced by left quote, and each ' preceded by \\=` and without +intervening ' is replaced by right quote. Left and right quote +characters are specified by ‘help-quote-translation’. + +\\=\\= 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; ptrdiff_t bsize; Lisp_Object tem; Lisp_Object keymap; - unsigned char *start; + unsigned char const *start; ptrdiff_t length, length_byte; Lisp_Object name; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; @@ -724,6 +750,21 @@ Otherwise, return a new string. */) name = Qnil; GCPRO4 (string, tem, keymap, name); + enum { unicode, grave_accent, apostrophe } quote_translation = unicode; + if (EQ (Vhelp_quote_translation, make_number ('`'))) + quote_translation = grave_accent; + else if (EQ (Vhelp_quote_translation, make_number ('\''))) + quote_translation = apostrophe; + else if (NILP (Vhelp_quote_translation) + && DISP_TABLE_P (Vstandard_display_table)) + { + Lisp_Object dv = DISP_CHAR_VECTOR (XCHAR_TABLE (Vstandard_display_table), + LEFT_SINGLE_QUOTATION_MARK); + if (VECTORP (dv) && ASIZE (dv) == 1 + && EQ (AREF (dv, 0), make_number ('`'))) + quote_translation = grave_accent; + } + multibyte = STRING_MULTIBYTE (string); nchars = 0; @@ -734,6 +775,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 +790,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 +813,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 +879,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 +948,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 +962,39 @@ Otherwise, return a new string. */) strp = SDATA (string) + idx; } } + else if (strp[0] == '`' && quote_translation == unicode) + { + in_quote = true; + start = LSQM; + subst_quote: + length = 1; + length_byte = 3; + idx = strp - SDATA (string) + 1; + goto subst; + } + else if (strp[0] == '`' && quote_translation == apostrophe) + { + *bufp++ = '\''; + strp++; + nchars++; + changed = true; + } + else if (strp[0] == '\'' && in_quote) + { + in_quote = false; + start = RSQM; + goto subst_quote; + } + else if (strp[0] == uLSQM0 && strp[1] == uLSQM1 + && (strp[2] == uLSQM2 || strp[2] == uRSQM2) + && quote_translation != unicode) + { + *bufp++ = (strp[2] == uLSQM2 && quote_translation == grave_accent + ? '`' : '\''); + strp += 3; + nchars++; + changed = true; + } else if (! multibyte) /* just copy other chars */ *bufp++ = *strp++, nchars++; else @@ -954,6 +1033,16 @@ syms_of_doc (void) doc: /* A list of files used to build this Emacs binary. */); Vbuild_files = Qnil; + DEFVAR_LISP ("help-quote-translation", Vhelp_quote_translation, + doc: /* Style to use for single quotes in help. +The value is a left single quote character of some style. +Quote \\=‘like this\\=’ if the value is ?\\=‘ (left single quotation mark). +Quote 'like this' if the value is ?' (apostrophe). +Quote \\=`like this' if the value is ?\\=` (grave accent). +The default value is nil, which means quote with left single quotation mark +if displayable, and with grave accent otherwise. */); + Vhelp_quote_translation = Qnil; + defsubr (&Sdocumentation); defsubr (&Sdocumentation_property); defsubr (&Ssnarf_documentation);