mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-23 07:19:15 +00:00
Revert "Extend ‘format’ to translate curved quotes"
This reverts commit 244c801689
.
This commit is contained in:
parent
0b0c9565d0
commit
6b1765e05d
@ -347,11 +347,19 @@ and @samp{\=\=} puts @samp{\=} into the output.
|
||||
@strong{Please note:} Each @samp{\} must be doubled when written in a
|
||||
string in Emacs Lisp.
|
||||
|
||||
@defvar text-quoting-style
|
||||
@cindex curved quotes
|
||||
@cindex curly quotes
|
||||
The value of the @code{text-quoting-style} variable specifies the style
|
||||
The value of this variable specifies the style
|
||||
@code{substitute-command-keys} uses when generating left and right
|
||||
quotes. @xref{Formatting Strings}, for more information.
|
||||
quotes. If the variable's value is @code{curve}, the style is
|
||||
@t{‘like this’} with curved single quotes. If the value is
|
||||
@code{straight}, the style is @t{'like this'} with straight
|
||||
apostrophes. If the value is @code{grave}, the style is @t{`like
|
||||
this'} with grave accent and apostrophe. The default value @code{nil}
|
||||
acts like @code{curve} if curved single quotes are displayable, and
|
||||
like @code{grave} otherwise.
|
||||
@end defvar
|
||||
|
||||
@defun substitute-command-keys string
|
||||
This function scans @var{string} for the above special sequences and
|
||||
|
@ -805,27 +805,22 @@ formatting feature described here; they differ from @code{format} only
|
||||
in how they use the result of formatting.
|
||||
|
||||
@defun format string &rest objects
|
||||
This function returns a string that is equivalent to copying
|
||||
This function returns a new string that is made by copying
|
||||
@var{string} and then replacing any format specification
|
||||
in the copy with encodings of the corresponding @var{objects}. The
|
||||
arguments @var{objects} are the computed values to be formatted.
|
||||
|
||||
The characters in @var{string}, other than the format specifications,
|
||||
are copied directly into the output, including their text properties,
|
||||
if any. If the output equals @var{string}, this function may return
|
||||
@var{string} itself rather than a new copy.
|
||||
if any.
|
||||
@end defun
|
||||
|
||||
@cindex @samp{%} in format
|
||||
@cindex format specification
|
||||
@cindex curved quotes
|
||||
@cindex curly quotes
|
||||
A format specification is a sequence of characters beginning with a
|
||||
@samp{%} or is a curved single quotation mark. Except for @samp{%%}
|
||||
and quotation marks, each format specification says how to represent
|
||||
one of the arguments @var{objects}. For example, if there
|
||||
is a @samp{%d} in @var{string}, the @code{format} function replaces it
|
||||
with the decimal representation of the integer to be formatted.
|
||||
@samp{%}. Thus, if there is a @samp{%d} in @var{string}, the
|
||||
@code{format} function replaces it with the printed representation of
|
||||
one of the values to be formatted (one of the arguments @var{objects}).
|
||||
For example:
|
||||
|
||||
@example
|
||||
@ -835,12 +830,11 @@ For example:
|
||||
@end group
|
||||
@end example
|
||||
|
||||
Since @code{format} interprets @samp{%}, @samp{‘} and @samp{’}
|
||||
characters as format
|
||||
Since @code{format} interprets @samp{%} characters as format
|
||||
specifications, you should @emph{never} pass an arbitrary string as
|
||||
the first argument. This is particularly true when the string is
|
||||
generated by some Lisp code. Unless the string is @emph{known} to
|
||||
never include any of the three special characters, pass @code{"%s"}, described
|
||||
never include any @samp{%} characters, pass @code{"%s"}, described
|
||||
below, as the first argument, and the string as the second, like this:
|
||||
|
||||
@example
|
||||
@ -914,27 +908,17 @@ is shorter.
|
||||
Replace the specification with a single @samp{%}. This format
|
||||
specification is unusual in that it does not use a value. For example,
|
||||
@code{(format "%% %d" 30)} returns @code{"% 30"}.
|
||||
|
||||
@item ‘
|
||||
@itemx ’
|
||||
@cindex curved quotes
|
||||
@cindex curly quotes
|
||||
Replace the specification with a left or right quote, respectively.
|
||||
Although typically a curved single quotation mark stands for itself,
|
||||
other quoting styles are available as per the variable
|
||||
@samp{text-quoting-style} described below.
|
||||
@end table
|
||||
|
||||
Any other format character after @samp{%} results in an @samp{Invalid format
|
||||
Any other format character results in an @samp{Invalid format
|
||||
operation} error.
|
||||
|
||||
Here are several examples, which assume the typical quoting style
|
||||
where curved single quotes stand for themselves:
|
||||
Here are several examples:
|
||||
|
||||
@example
|
||||
@group
|
||||
(format "The name of this buffer is ‘%s’." (buffer-name))
|
||||
@result{} "The name of this buffer is ‘strings.texi’."
|
||||
(format "The name of this buffer is %s." (buffer-name))
|
||||
@result{} "The name of this buffer is strings.texi."
|
||||
|
||||
(format "The buffer object prints as %qs." (current-buffer))
|
||||
@result{} "The buffer object prints as ‘strings.texi’."
|
||||
@ -948,7 +932,7 @@ where curved single quotes stand for themselves:
|
||||
|
||||
@cindex field width
|
||||
@cindex padding
|
||||
A @samp{%} specification can have a @dfn{width}, which is a decimal number
|
||||
A specification can have a @dfn{width}, which is a decimal number
|
||||
between the @samp{%} and the specification character. If the printed
|
||||
representation of the object contains fewer characters than this
|
||||
width, @code{format} extends it with padding. The width specifier is
|
||||
@ -964,7 +948,7 @@ the width specifier normally consists of spaces inserted on the left:
|
||||
If the width is too small, @code{format} does not truncate the
|
||||
object's printed representation. Thus, you can use a width to specify
|
||||
a minimum spacing between columns with no risk of losing information.
|
||||
In the following two examples, @samp{%7s} specifies a minimum width
|
||||
In the following three examples, @samp{%7s} specifies a minimum width
|
||||
of 7. In the first case, the string inserted in place of @samp{%7s}
|
||||
has only 3 letters, and needs 4 blank spaces as padding. In the
|
||||
second case, the string @code{"specification"} is 13 letters wide but
|
||||
@ -972,12 +956,12 @@ is not truncated.
|
||||
|
||||
@example
|
||||
@group
|
||||
(format "The word ‘%7s’ has %d letters in it."
|
||||
(format "The word '%7s' has %d letters in it."
|
||||
"foo" (length "foo"))
|
||||
@result{} "The word ‘ foo’ has 3 letters in it."
|
||||
(format "The word ‘%7s’ has %d letters in it."
|
||||
@result{} "The word ' foo' has 3 letters in it."
|
||||
(format "The word '%7s' has %d letters in it."
|
||||
"specification" (length "specification"))
|
||||
@result{} "The word ‘specification’ has 13 letters in it."
|
||||
@result{} "The word 'specification' has 13 letters in it."
|
||||
@end group
|
||||
@end example
|
||||
|
||||
@ -1022,14 +1006,14 @@ variable @samp{text-quoting-style} described below.
|
||||
(format "%q-6d is padded on the right" 123)
|
||||
@result{} "‘123 ’ is padded on the right"
|
||||
|
||||
(format "The word ‘%-7s’ actually has %d letters in it."
|
||||
(format "The word '%-7s' actually has %d letters in it."
|
||||
"foo" (length "foo"))
|
||||
@result{} "The word ‘foo ’ actually has 3 letters in it."
|
||||
@result{} "The word 'foo ' actually has 3 letters in it."
|
||||
@end group
|
||||
@end example
|
||||
|
||||
@cindex precision in format specifications
|
||||
The @samp{%} specification characters allow an optional @dfn{precision}
|
||||
All the specification characters allow an optional @dfn{precision}
|
||||
before the character (after the width, if present). The precision is
|
||||
a decimal-point @samp{.} followed by a digit-string. For the
|
||||
floating-point specifications (@samp{%e}, @samp{%f}, @samp{%g}), the
|
||||
@ -1040,19 +1024,6 @@ shows only the first three characters of the representation for
|
||||
@var{object}. Precision has no effect for other specification
|
||||
characters.
|
||||
|
||||
@defvar text-quoting-style
|
||||
@cindex curved quotes
|
||||
@cindex curly quotes
|
||||
This variable specifies the style @code{format} uses when generating
|
||||
left and right quotes. If the value is @code{curve}, the style is
|
||||
@t{‘like this’} with curved single quotes. If the value is
|
||||
@code{straight}, the style is @t{'like this'} with straight
|
||||
apostrophes. If the value is @code{grave}, the style is @t{`like
|
||||
this'} with grave accent and apostrophe. The default value @code{nil}
|
||||
acts like @code{curve} if curved single quotes are displayable, and
|
||||
like @code{grave} otherwise.
|
||||
@end defvar
|
||||
|
||||
@node Case Conversion
|
||||
@section Case Conversion in Lisp
|
||||
@cindex upper case
|
||||
|
13
etc/NEWS
13
etc/NEWS
@ -909,19 +909,6 @@ 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.
|
||||
|
||||
+++
|
||||
** ‘format’ now replaces curved single quotes.
|
||||
That is, it replaces strings' curved single quotes (also known as
|
||||
curly quotes) as per the value of the new custom variable
|
||||
‘text-quoting-style’: ‘curve’ means replace curved quotes with
|
||||
themselves ‘like this’, ‘straight’ means use straight apostrophes
|
||||
'like this', ‘grave’ means use grave accent and apostrophe `like
|
||||
this', and nil (default) means use curved quotes if displayable and
|
||||
grave accent and apostrophe otherwise. Because it now may be used
|
||||
in many contexts where it's a no-op, ‘format’ is no longer required to
|
||||
create a string, and may return its first argument if the argument
|
||||
already has the correct value.
|
||||
|
||||
+++
|
||||
** New ‘format’ flag ‘q’
|
||||
The new ‘q’ flag causes ‘format’ to quote the output representation as
|
||||
|
@ -365,7 +365,7 @@ C-w Describe how there is no warranty for Calc."
|
||||
(let (Info-history)
|
||||
(Info-goto-node (buffer-substring (match-beginning 1) (match-end 1))))
|
||||
(let* ((string-target (or target thing))
|
||||
(quoted (concat "['`‘]" (regexp-quote string-target) "['’]"))
|
||||
(quoted (format "['`‘]%s['’]" (regexp-quote string-target)))
|
||||
(bracketed (format "\\[%s\\]\\|(%s)\\|\\<The[ \n]%s"
|
||||
quoted quoted quoted)))
|
||||
(or (let ((case-fold-search nil))
|
||||
|
@ -331,10 +331,9 @@ which more-or-less shadow%s %s's corresponding table%s."
|
||||
"\n\nThis mode "
|
||||
(concat
|
||||
"\n\nIn addition to any hooks its parent mode "
|
||||
(if (string-match (concat "[`%‘]"
|
||||
(if (string-match (format "[`‘]%s['’]"
|
||||
(regexp-quote
|
||||
(symbol-name parent))
|
||||
"['%’]")
|
||||
(symbol-name parent)))
|
||||
docstring)
|
||||
nil
|
||||
(format "`%s' " parent))
|
||||
|
@ -3398,12 +3398,10 @@ Give an empty topic name to go to the Index node itself."
|
||||
(re-search-forward (format
|
||||
"[a-zA-Z]+: [a-zA-Z0-9_ *&]+ %s\\( \\|$\\)"
|
||||
(regexp-quote name)) nil t)
|
||||
(search-forward (concat "['`‘]" name "['’]") nil t)
|
||||
(search-forward (format "['`‘]%s['’]" name) nil t)
|
||||
(and (string-match "\\`.*\\( (.*)\\)\\'" name)
|
||||
(search-forward
|
||||
(concat "['`%‘]"
|
||||
(substring name 0 (match-beginning 1))
|
||||
"['%’]")
|
||||
(format "['`‘]%s['’]" (substring name 0 (match-beginning 1)))
|
||||
nil t))
|
||||
(search-forward name nil t)
|
||||
;; Try again without the " <1>" makeinfo can append
|
||||
|
208
src/editfns.c
208
src/editfns.c
@ -3800,9 +3800,8 @@ DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
|
||||
The first argument is a format control string.
|
||||
The other arguments are substituted into it to make the result, a string.
|
||||
|
||||
The format control string may contain ordinary characters,
|
||||
%-sequences meaning to substitute the next available argument,
|
||||
and curved single quotation marks meaning to substitute quotes.
|
||||
The format control string may contain %-sequences meaning to substitute
|
||||
the next available argument:
|
||||
|
||||
%s means print a string argument. Actually, prints any object, with `princ'.
|
||||
%d means print as number in decimal (%o octal, %x hex).
|
||||
@ -3850,12 +3849,6 @@ precision specifier says how many decimal places to show; if zero, the
|
||||
decimal point itself is omitted. For %s and %S, the precision
|
||||
specifier truncates the string to the given width.
|
||||
|
||||
\\=‘ and \\=’ means print left and right quotes as per
|
||||
‘text-quoting-style’.
|
||||
|
||||
Return the first argument if it contains no format directives.
|
||||
Otherwise, return a new string.
|
||||
|
||||
usage: (format STRING &rest OBJECTS) */)
|
||||
(ptrdiff_t nargs, Lisp_Object *args)
|
||||
{
|
||||
@ -3868,7 +3861,6 @@ usage: (format STRING &rest OBJECTS) */)
|
||||
ptrdiff_t buf_save_value_index IF_LINT (= 0);
|
||||
char *format, *end, *format_start;
|
||||
ptrdiff_t formatlen, nchars;
|
||||
bool changed = false;
|
||||
/* True if the format is multibyte. */
|
||||
bool multibyte_format = 0;
|
||||
/* True if the output should be a multibyte string,
|
||||
@ -4020,7 +4012,6 @@ usage: (format STRING &rest OBJECTS) */)
|
||||
if (format == end)
|
||||
error ("Format string ends in middle of format specifier");
|
||||
|
||||
changed = true;
|
||||
memset (&discarded[format0 - format_start], 1, format - format0);
|
||||
conversion = *format;
|
||||
if (conversion == '%')
|
||||
@ -4493,20 +4484,6 @@ usage: (format STRING &rest OBJECTS) */)
|
||||
|
||||
convbytes = format - src;
|
||||
memset (&discarded[src + 1 - format_start], 2, convbytes - 1);
|
||||
|
||||
if (quoting_style != CURVE_QUOTING_STYLE && convbytes == 3
|
||||
&& (unsigned char) src[0] == uLSQM0
|
||||
&& (unsigned char) src[1] == uLSQM1
|
||||
&& ((unsigned char) src[2] == uLSQM2
|
||||
|| (unsigned char) src[2] == uRSQM2))
|
||||
{
|
||||
convbytes = 1;
|
||||
str[0] = (((unsigned char) src[2] == uLSQM2
|
||||
&& quoting_style == GRAVE_QUOTING_STYLE)
|
||||
? '`' : '\'');
|
||||
src = (char *) str;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4518,7 +4495,6 @@ usage: (format STRING &rest OBJECTS) */)
|
||||
int c = BYTE8_TO_CHAR (uc);
|
||||
convbytes = CHAR_STRING (c, str);
|
||||
src = (char *) str;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4566,119 +4542,113 @@ usage: (format STRING &rest OBJECTS) */)
|
||||
if (bufsize < p - buf)
|
||||
emacs_abort ();
|
||||
|
||||
if (!changed)
|
||||
val = args[0];
|
||||
else
|
||||
if (maybe_combine_byte)
|
||||
nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf);
|
||||
val = make_specified_string (buf, nchars, p - buf, multibyte);
|
||||
|
||||
/* If the format string has text properties, or any of the string
|
||||
arguments has text properties, set up text properties of the
|
||||
result string. */
|
||||
|
||||
if (string_intervals (args[0]) || arg_intervals)
|
||||
{
|
||||
if (maybe_combine_byte)
|
||||
nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf);
|
||||
val = make_specified_string (buf, nchars, p - buf, multibyte);
|
||||
Lisp_Object len, new_len, props;
|
||||
struct gcpro gcpro1;
|
||||
|
||||
/* If the format string has text properties, or any of the string
|
||||
arguments has text properties, set up text properties of the
|
||||
result string. */
|
||||
/* Add text properties from the format string. */
|
||||
len = make_number (SCHARS (args[0]));
|
||||
props = text_property_list (args[0], make_number (0), len, Qnil);
|
||||
GCPRO1 (props);
|
||||
|
||||
if (string_intervals (args[0]) || arg_intervals)
|
||||
if (CONSP (props))
|
||||
{
|
||||
Lisp_Object len, new_len, props;
|
||||
struct gcpro gcpro1;
|
||||
ptrdiff_t bytepos = 0, position = 0, translated = 0;
|
||||
ptrdiff_t argn = 1;
|
||||
Lisp_Object list;
|
||||
|
||||
/* Add text properties from the format string. */
|
||||
len = make_number (SCHARS (args[0]));
|
||||
props = text_property_list (args[0], make_number (0), len, Qnil);
|
||||
GCPRO1 (props);
|
||||
/* Adjust the bounds of each text property
|
||||
to the proper start and end in the output string. */
|
||||
|
||||
if (CONSP (props))
|
||||
/* Put the positions in PROPS in increasing order, so that
|
||||
we can do (effectively) one scan through the position
|
||||
space of the format string. */
|
||||
props = Fnreverse (props);
|
||||
|
||||
/* BYTEPOS is the byte position in the format string,
|
||||
POSITION is the untranslated char position in it,
|
||||
TRANSLATED is the translated char position in BUF,
|
||||
and ARGN is the number of the next arg we will come to. */
|
||||
for (list = props; CONSP (list); list = XCDR (list))
|
||||
{
|
||||
ptrdiff_t bytepos = 0, position = 0, translated = 0;
|
||||
ptrdiff_t argn = 1;
|
||||
Lisp_Object list;
|
||||
Lisp_Object item;
|
||||
ptrdiff_t pos;
|
||||
|
||||
/* Adjust the bounds of each text property
|
||||
to the proper start and end in the output string. */
|
||||
item = XCAR (list);
|
||||
|
||||
/* Put the positions in PROPS in increasing order, so that
|
||||
we can do (effectively) one scan through the position
|
||||
space of the format string. */
|
||||
props = Fnreverse (props);
|
||||
/* First adjust the property start position. */
|
||||
pos = XINT (XCAR (item));
|
||||
|
||||
/* BYTEPOS is the byte position in the format string,
|
||||
POSITION is the untranslated char position in it,
|
||||
TRANSLATED is the translated char position in BUF,
|
||||
and ARGN is the number of the next arg we will come to. */
|
||||
for (list = props; CONSP (list); list = XCDR (list))
|
||||
/* Advance BYTEPOS, POSITION, TRANSLATED and ARGN
|
||||
up to this position. */
|
||||
for (; position < pos; bytepos++)
|
||||
{
|
||||
Lisp_Object item;
|
||||
ptrdiff_t pos;
|
||||
|
||||
item = XCAR (list);
|
||||
|
||||
/* First adjust the property start position. */
|
||||
pos = XINT (XCAR (item));
|
||||
|
||||
/* Advance BYTEPOS, POSITION, TRANSLATED and ARGN
|
||||
up to this position. */
|
||||
for (; position < pos; bytepos++)
|
||||
if (! discarded[bytepos])
|
||||
position++, translated++;
|
||||
else if (discarded[bytepos] == 1)
|
||||
{
|
||||
if (! discarded[bytepos])
|
||||
position++, translated++;
|
||||
else if (discarded[bytepos] == 1)
|
||||
position++;
|
||||
if (translated == info[argn].start)
|
||||
{
|
||||
position++;
|
||||
if (translated == info[argn].start)
|
||||
{
|
||||
translated += info[argn].end - info[argn].start;
|
||||
argn++;
|
||||
}
|
||||
translated += info[argn].end - info[argn].start;
|
||||
argn++;
|
||||
}
|
||||
}
|
||||
|
||||
XSETCAR (item, make_number (translated));
|
||||
|
||||
/* Likewise adjust the property end position. */
|
||||
pos = XINT (XCAR (XCDR (item)));
|
||||
|
||||
for (; position < pos; bytepos++)
|
||||
{
|
||||
if (! discarded[bytepos])
|
||||
position++, translated++;
|
||||
else if (discarded[bytepos] == 1)
|
||||
{
|
||||
position++;
|
||||
if (translated == info[argn].start)
|
||||
{
|
||||
translated += info[argn].end - info[argn].start;
|
||||
argn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XSETCAR (XCDR (item), make_number (translated));
|
||||
}
|
||||
|
||||
add_text_properties_from_list (val, props, make_number (0));
|
||||
XSETCAR (item, make_number (translated));
|
||||
|
||||
/* Likewise adjust the property end position. */
|
||||
pos = XINT (XCAR (XCDR (item)));
|
||||
|
||||
for (; position < pos; bytepos++)
|
||||
{
|
||||
if (! discarded[bytepos])
|
||||
position++, translated++;
|
||||
else if (discarded[bytepos] == 1)
|
||||
{
|
||||
position++;
|
||||
if (translated == info[argn].start)
|
||||
{
|
||||
translated += info[argn].end - info[argn].start;
|
||||
argn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XSETCAR (XCDR (item), make_number (translated));
|
||||
}
|
||||
|
||||
/* Add text properties from arguments. */
|
||||
if (arg_intervals)
|
||||
for (n = 1; n < nargs; ++n)
|
||||
if (info[n].intervals)
|
||||
{
|
||||
len = make_number (SCHARS (args[n]));
|
||||
new_len = make_number (info[n].end - info[n].start);
|
||||
props = text_property_list (args[n], make_number (0),
|
||||
len, Qnil);
|
||||
props = extend_property_ranges (props, new_len);
|
||||
/* If successive arguments have properties, be sure that
|
||||
the value of `composition' property be the copy. */
|
||||
if (n > 1 && info[n - 1].end)
|
||||
make_composition_value_copy (props);
|
||||
add_text_properties_from_list (val, props,
|
||||
make_number (info[n].start));
|
||||
}
|
||||
|
||||
UNGCPRO;
|
||||
add_text_properties_from_list (val, props, make_number (0));
|
||||
}
|
||||
|
||||
/* Add text properties from arguments. */
|
||||
if (arg_intervals)
|
||||
for (n = 1; n < nargs; ++n)
|
||||
if (info[n].intervals)
|
||||
{
|
||||
len = make_number (SCHARS (args[n]));
|
||||
new_len = make_number (info[n].end - info[n].start);
|
||||
props = text_property_list (args[n], make_number (0), len, Qnil);
|
||||
props = extend_property_ranges (props, new_len);
|
||||
/* If successive arguments have properties, be sure that
|
||||
the value of `composition' property be the copy. */
|
||||
if (n > 1 && info[n - 1].end)
|
||||
make_composition_value_copy (props);
|
||||
add_text_properties_from_list (val, props,
|
||||
make_number (info[n].start));
|
||||
}
|
||||
|
||||
UNGCPRO;
|
||||
}
|
||||
|
||||
/* If we allocated BUF or INFO with malloc, free it too. */
|
||||
|
Loading…
Reference in New Issue
Block a user