diff options
| author | Paul Eggert | 2015-08-24 23:37:18 -0700 |
|---|---|---|
| committer | Paul Eggert | 2015-08-24 23:57:21 -0700 |
| commit | 68280c5ee9b87d874ffa7c111b3cac7e634cee22 (patch) | |
| tree | 955f3f692c7254074cac682c4e7e64b6f1361a35 | |
| parent | 0db4992d2778a2da4dee8ca07cde8c5e206f5250 (diff) | |
| download | emacs-68280c5ee9b87d874ffa7c111b3cac7e634cee22.tar.gz emacs-68280c5ee9b87d874ffa7c111b3cac7e634cee22.zip | |
Treat ' like ’ even when not matching `
This is simpler and easier to explain, and should encourage better
typography. Do this in Electric Quote mode and when translating
quotes in docstrings. Inspired by a suggestion by Dmitry Gutov in:
https://lists.gnu.org/archive/html/emacs-devel/2015-08/msg00806.html
* doc/emacs/text.texi (Quotation Marks):
* doc/lispref/help.texi (Keys in Documentation):
* etc/NEWS:
Document this.
* lisp/electric.el (electric-quote-post-self-insert-function):
* src/doc.c (Fsubstitute_command_keys):
Always treat ' like ’ even when not matched by an open quote.
| -rw-r--r-- | doc/emacs/text.texi | 12 | ||||
| -rw-r--r-- | doc/lispref/help.texi | 20 | ||||
| -rw-r--r-- | etc/NEWS | 2 | ||||
| -rw-r--r-- | lisp/electric.el | 33 | ||||
| -rw-r--r-- | src/doc.c | 25 |
5 files changed, 32 insertions, 60 deletions
diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi index 5a13f208876..31760b70b4c 100644 --- a/doc/emacs/text.texi +++ b/doc/emacs/text.texi | |||
| @@ -420,13 +420,11 @@ left and right single or double quotation marks @t{‘like this’} or | |||
| 420 | @t{“like this”}. Typewriter quotes are simple and portable; curved | 420 | @t{“like this”}. Typewriter quotes are simple and portable; curved |
| 421 | quotes are less ambiguous and typically look nicer. | 421 | quotes are less ambiguous and typically look nicer. |
| 422 | 422 | ||
| 423 | Electric Quote mode makes it easier to type curved quotes. It | 423 | Electric Quote mode makes it easier to type curved quotes. As you |
| 424 | optionally converts a quotation's grave accent and apostrophe @t{`like | 424 | type characters it optionally converts @t{`} to @t{‘}, @t{'} to @t{’}, |
| 425 | this'} to single quotation marks @t{‘like this’}. Similarly, it | 425 | @t{``} to @t{“}, and @t{''} to @t{”}. These conversions are |
| 426 | converts a quotation's double grave accent and double apostrophe | 426 | suppressed in buffers whose coding systems cannot represent curved |
| 427 | @t{``like this''} to double quotation marks @t{“like this”}. These | 427 | quote characters. |
| 428 | conversions are suppressed in buffers whose coding systems cannot | ||
| 429 | represent curved quote characters. | ||
| 430 | 428 | ||
| 431 | @vindex electric-quote-paragraph | 429 | @vindex electric-quote-paragraph |
| 432 | @vindex electric-quote-comment | 430 | @vindex electric-quote-comment |
diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi index ab884f8dc80..44c09a2085a 100644 --- a/doc/lispref/help.texi +++ b/doc/lispref/help.texi | |||
| @@ -318,25 +318,13 @@ stands for no text itself. It is used only for a side effect: it | |||
| 318 | specifies @var{mapvar}'s value as the keymap for any following | 318 | specifies @var{mapvar}'s value as the keymap for any following |
| 319 | @samp{\[@var{command}]} sequences in this documentation string. | 319 | @samp{\[@var{command}]} sequences in this documentation string. |
| 320 | 320 | ||
| 321 | @item ` | ||
| 322 | (grave accent) stands for a left quote, and alters the interpretation | ||
| 323 | of the next unmatched apostrophe. | ||
| 324 | |||
| 325 | @item ' | ||
| 326 | (apostrophe) stands for a right quote if preceded by grave accent and | ||
| 327 | there are no intervening apostrophes. Otherwise, apostrophe stands | ||
| 328 | for itself. | ||
| 329 | |||
| 330 | @item ‘ | 321 | @item ‘ |
| 331 | (left single quotation mark) stands for a left quote. | 322 | @itemx ` |
| 323 | (left single quotation mark and grave accent) both stand for a left quote. | ||
| 332 | 324 | ||
| 333 | @item ’ | 325 | @item ’ |
| 334 | (right single quotation mark) stands for a right quote. | 326 | @itemx ' |
| 335 | 327 | (right single quotation mark and apostrophe) both stand for a right quote. | |
| 336 | @item ' | ||
| 337 | (apostrophe) stands for a right quote if | ||
| 338 | preceded by grave accent and there are no intervening apostrophes. | ||
| 339 | Otherwise, apostrophe stands for itself. | ||
| 340 | 328 | ||
| 341 | @item \= | 329 | @item \= |
| 342 | quotes the following character and is discarded; thus, @samp{\=`} puts | 330 | quotes the following character and is discarded; thus, @samp{\=`} puts |
| @@ -923,7 +923,7 @@ Quotes in info files are not translated. | |||
| 923 | That is, it converts documentation strings’ quoting style as per the | 923 | That is, it converts documentation strings’ quoting style as per the |
| 924 | value of ‘text-quoting-style’. Doc strings in source code can use | 924 | value of ‘text-quoting-style’. Doc strings in source code can use |
| 925 | either curved quotes or grave accent and apostrophe. As before, | 925 | either curved quotes or grave accent and apostrophe. As before, |
| 926 | isolated apostrophes and characters preceded by \= are output as-is. | 926 | characters preceded by \= are output as-is. |
| 927 | 927 | ||
| 928 | +++ | 928 | +++ |
| 929 | ** Message-issuing functions ‘error’, ‘message’, etc. now convert quotes. | 929 | ** Message-issuing functions ‘error’, ‘message’, etc. now convert quotes. |
diff --git a/lisp/electric.el b/lisp/electric.el index 8ca09316bcb..bef5bb9fec7 100644 --- a/lisp/electric.el +++ b/lisp/electric.el | |||
| @@ -453,7 +453,7 @@ This requotes when a quoting key is typed." | |||
| 453 | (save-excursion | 453 | (save-excursion |
| 454 | (if (eq last-command-event ?\`) | 454 | (if (eq last-command-event ?\`) |
| 455 | (cond ((and (electric--insertable-p "“") | 455 | (cond ((and (electric--insertable-p "“") |
| 456 | (re-search-backward "[`‘]`" (- (point) 2) t)) | 456 | (search-backward "‘`" (- (point) 2) t)) |
| 457 | (replace-match "“") | 457 | (replace-match "“") |
| 458 | (when (and electric-pair-mode | 458 | (when (and electric-pair-mode |
| 459 | (eq (cdr-safe | 459 | (eq (cdr-safe |
| @@ -465,19 +465,14 @@ This requotes when a quoting key is typed." | |||
| 465 | (search-backward "`" (1- (point)) t)) | 465 | (search-backward "`" (1- (point)) t)) |
| 466 | (replace-match "‘") | 466 | (replace-match "‘") |
| 467 | (setq last-command-event ?‘))) | 467 | (setq last-command-event ?‘))) |
| 468 | (let ((pos (point))) | 468 | (cond ((and (electric--insertable-p "”") |
| 469 | (if (memq (char-before (1- (point))) '(?\' ?’)) | 469 | (search-backward "’'" (- (point) 2) t)) |
| 470 | (when (and (search-backward "“" start t) | 470 | (replace-match "”") |
| 471 | (eq pos (re-search-forward | 471 | (setq last-command-event ?”)) |
| 472 | "“\\(\\([^‘”]\\|‘[^‘’”]*’\\)*\\)['’]'" | 472 | ((and (electric--insertable-p "’") |
| 473 | pos t))) | 473 | (search-backward "'" (1- (point)) t)) |
| 474 | (replace-match "“\\1”") | 474 | (replace-match "’") |
| 475 | (setq last-command-event ?”)) | 475 | (setq last-command-event ?’))))))))) |
| 476 | (when (and (search-backward "‘" start t) | ||
| 477 | (eq pos (re-search-forward | ||
| 478 | "‘\\([^’]*\\)'" pos t))) | ||
| 479 | (replace-match "‘\\1’") | ||
| 480 | (setq last-command-event ?’)))))))))) | ||
| 481 | 476 | ||
| 482 | (put 'electric-quote-post-self-insert-function 'priority 10) | 477 | (put 'electric-quote-post-self-insert-function 'priority 10) |
| 483 | 478 | ||
| @@ -488,11 +483,11 @@ With a prefix argument ARG, enable Electric Quote mode if | |||
| 488 | ARG is positive, and disable it otherwise. If called from Lisp, | 483 | ARG is positive, and disable it otherwise. If called from Lisp, |
| 489 | enable the mode if ARG is omitted or nil. | 484 | enable the mode if ARG is omitted or nil. |
| 490 | 485 | ||
| 491 | When enabled, this replaces \\=`foo bar' with \\=‘foo bar\\=’ and replaces | 486 | When enabled, as you type this replaces \\=` with \\=‘, \\=' with \\=’, |
| 492 | \\=`\\=`foo bar'' with “foo bar” as you type. This occurs only in | 487 | \\=`\\=` with “, and \\='\\=' with ”. This occurs only in comments, strings, |
| 493 | comments, strings, and text paragraphs, and these are selectively | 488 | and text paragraphs, and these are selectively controlled with |
| 494 | controlled with ‘electric-quote-comment’, | 489 | ‘electric-quote-comment’, ‘electric-quote-string’, and |
| 495 | ‘electric-quote-string’, and ‘electric-quote-paragraph’. | 490 | ‘electric-quote-paragraph’. |
| 496 | 491 | ||
| 497 | This is a global minor mode. To toggle the mode in a single buffer, | 492 | This is a global minor mode. To toggle the mode in a single buffer, |
| 498 | use ‘electric-quote-local-mode’." | 493 | use ‘electric-quote-local-mode’." |
| @@ -731,10 +731,9 @@ summary). | |||
| 731 | Each substring of the form \\=\\<MAPVAR> specifies the use of MAPVAR | 731 | Each substring of the form \\=\\<MAPVAR> specifies the use of MAPVAR |
| 732 | as the keymap for future \\=\\[COMMAND] substrings. | 732 | as the keymap for future \\=\\[COMMAND] substrings. |
| 733 | 733 | ||
| 734 | Each \\=‘ and \\=’ are replaced by left and right quote. Each \\=` is | 734 | Each \\=‘ and \\=` is replaced by left quote, and each \\=’ and \\=' |
| 735 | replaced by left quote, and each ' preceded by \\=` and without | 735 | is replaced by right quote. Left and right quote characters are |
| 736 | intervening ' is replaced by right quote. Left and right quote | 736 | specified by ‘text-quoting-style’. |
| 737 | characters are specified by ‘text-quoting-style’. | ||
| 738 | 737 | ||
| 739 | \\=\\= quotes the following character and is discarded; thus, | 738 | \\=\\= quotes the following character and is discarded; thus, |
| 740 | \\=\\=\\=\\= puts \\=\\= into the output, \\=\\=\\=\\[ puts \\=\\[ into the output, and | 739 | \\=\\=\\=\\= puts \\=\\= into the output, \\=\\=\\=\\[ puts \\=\\[ into the output, and |
| @@ -746,7 +745,6 @@ Otherwise, return a new string. */) | |||
| 746 | { | 745 | { |
| 747 | char *buf; | 746 | char *buf; |
| 748 | bool changed = false; | 747 | bool changed = false; |
| 749 | bool in_quote = false; | ||
| 750 | unsigned char *strp; | 748 | unsigned char *strp; |
| 751 | char *bufp; | 749 | char *bufp; |
| 752 | ptrdiff_t idx; | 750 | ptrdiff_t idx; |
| @@ -971,11 +969,10 @@ Otherwise, return a new string. */) | |||
| 971 | strp = SDATA (string) + idx; | 969 | strp = SDATA (string) + idx; |
| 972 | } | 970 | } |
| 973 | } | 971 | } |
| 974 | else if (strp[0] == '`' && quoting_style == CURVE_QUOTING_STYLE) | 972 | else if ((strp[0] == '`' || strp[0] == '\'') |
| 973 | && quoting_style == CURVE_QUOTING_STYLE) | ||
| 975 | { | 974 | { |
| 976 | in_quote = true; | 975 | start = strp[0] == '`' ? LSQM : RSQM; |
| 977 | start = LSQM; | ||
| 978 | subst_quote: | ||
| 979 | length = 1; | 976 | length = 1; |
| 980 | length_byte = 3; | 977 | length_byte = 3; |
| 981 | idx = strp - SDATA (string) + 1; | 978 | idx = strp - SDATA (string) + 1; |
| @@ -988,12 +985,6 @@ Otherwise, return a new string. */) | |||
| 988 | nchars++; | 985 | nchars++; |
| 989 | changed = true; | 986 | changed = true; |
| 990 | } | 987 | } |
| 991 | else if (strp[0] == '\'' && in_quote) | ||
| 992 | { | ||
| 993 | in_quote = false; | ||
| 994 | start = RSQM; | ||
| 995 | goto subst_quote; | ||
| 996 | } | ||
| 997 | else if (strp[0] == uLSQM0 && strp[1] == uLSQM1 | 988 | else if (strp[0] == uLSQM0 && strp[1] == uLSQM1 |
| 998 | && (strp[2] == uLSQM2 || strp[2] == uRSQM2) | 989 | && (strp[2] == uLSQM2 || strp[2] == uRSQM2) |
| 999 | && quoting_style != CURVE_QUOTING_STYLE) | 990 | && quoting_style != CURVE_QUOTING_STYLE) |
| @@ -1108,8 +1099,8 @@ syms_of_doc (void) | |||
| 1108 | DEFVAR_LISP ("text-quoting-style", Vtext_quoting_style, | 1099 | DEFVAR_LISP ("text-quoting-style", Vtext_quoting_style, |
| 1109 | doc: /* Style to use for single quotes when generating text. | 1100 | doc: /* Style to use for single quotes when generating text. |
| 1110 | ‘curve’ means quote with curved single quotes \\=‘like this\\=’. | 1101 | ‘curve’ means quote with curved single quotes \\=‘like this\\=’. |
| 1111 | ‘straight’ means quote with straight apostrophes 'like this'. | 1102 | ‘straight’ means quote with straight apostrophes \\='like this\\='. |
| 1112 | ‘grave’ means quote with grave accent and apostrophe \\=`like this'. | 1103 | ‘grave’ means quote with grave accent and apostrophe \\=`like this\\='. |
| 1113 | The default value nil acts like ‘curve’ if curved single quotes are | 1104 | The default value nil acts like ‘curve’ if curved single quotes are |
| 1114 | displayable, and like ‘grave’ otherwise. */); | 1105 | displayable, and like ‘grave’ otherwise. */); |
| 1115 | Vtext_quoting_style = Qnil; | 1106 | Vtext_quoting_style = Qnil; |