From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Noam Postavsky Newsgroups: gmane.emacs.bugs Subject: bug#32939: 27.0.50; Don't reject confusable quotes, just fontify & mention them in error messages Date: Thu, 04 Oct 2018 19:58:10 -0400 Message-ID: <87lg7dmfhp.fsf@gmail.com> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: blaine.gmane.org 1538697430 23247 195.159.176.226 (4 Oct 2018 23:57:10 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Thu, 4 Oct 2018 23:57:10 +0000 (UTC) To: 32939@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Fri Oct 05 01:57:05 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g8DUO-0005wj-7X for geb-bug-gnu-emacs@m.gmane.org; Fri, 05 Oct 2018 01:57:04 +0200 Original-Received: from localhost ([::1]:60576 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g8DWU-0001Xi-Sb for geb-bug-gnu-emacs@m.gmane.org; Thu, 04 Oct 2018 19:59:14 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:50403) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g8DWM-0001XR-1j for bug-gnu-emacs@gnu.org; Thu, 04 Oct 2018 19:59:07 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g8DWI-0001xT-Lo for bug-gnu-emacs@gnu.org; Thu, 04 Oct 2018 19:59:05 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:32992) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1g8DWI-0001xD-Fw for bug-gnu-emacs@gnu.org; Thu, 04 Oct 2018 19:59:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1g8DWI-0003Ys-CS for bug-gnu-emacs@gnu.org; Thu, 04 Oct 2018 19:59:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Noam Postavsky Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 04 Oct 2018 23:59:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 32939 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.153869751013639 (code B ref -1); Thu, 04 Oct 2018 23:59:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 4 Oct 2018 23:58:30 +0000 Original-Received: from localhost ([127.0.0.1]:37250 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g8DVl-0003Xv-N3 for submit@debbugs.gnu.org; Thu, 04 Oct 2018 19:58:30 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:40697) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g8DVj-0003Xe-FN for submit@debbugs.gnu.org; Thu, 04 Oct 2018 19:58:28 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g8DVc-00018z-BD for submit@debbugs.gnu.org; Thu, 04 Oct 2018 19:58:22 -0400 Original-Received: from lists.gnu.org ([2001:4830:134:3::11]:33840) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1g8DVc-00018e-6E for submit@debbugs.gnu.org; Thu, 04 Oct 2018 19:58:20 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:50304) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g8DVa-0001Ao-Ec for bug-gnu-emacs@gnu.org; Thu, 04 Oct 2018 19:58:20 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g8DVX-0000wJ-2a for bug-gnu-emacs@gnu.org; Thu, 04 Oct 2018 19:58:18 -0400 Original-Received: from mail-it1-x12b.google.com ([2607:f8b0:4864:20::12b]:33894) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1g8DVW-0000s8-N7 for bug-gnu-emacs@gnu.org; Thu, 04 Oct 2018 19:58:15 -0400 Original-Received: by mail-it1-x12b.google.com with SMTP id l127-v6so3146016ith.1 for ; Thu, 04 Oct 2018 16:58:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:mime-version; bh=ERrk1mjpDKfGhF2pE2tgfFLtyM/2SMxH6A/K4rlfzCE=; b=mOLc/C/gWLyxYGGjABr8z2LgvjzA4K97t5kok3xYqy7/6T/eWLIz+oHS0bjDuNea/r 03Hk/g+MDBVzmrlhKoy2M5DdQD8tISqQS0khpE5u7MpvEXyVoUz45i8GADWsPWq8P1Im sEFMg9zgQV95gZ+T+0Z6zqY0Q8Brm2txndgFMzkwYQMHuD8gRTpwKyJQtTLwb1HQjEIy NoHVVV5oiOlMEJfUyaBcfCf+//a0aMUZlAyiO1ux99tRVs02UcImMG45IsvOVbCJ0D1X p1RYfxGutPH/0rvh72bWyh3Yavknv+kz8ggiktmgv75m7h46O0uI0PenIYDPKObT/dDg 517Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version; bh=ERrk1mjpDKfGhF2pE2tgfFLtyM/2SMxH6A/K4rlfzCE=; b=i1c/3lEMGl6CMZynEjkzWfUkov2eO4CINBX/LZh6P1zwJEQxncbsYGLsMP9kzkKOl1 6UZ1DdlmusCG03Oc+ANLaw4kaJy+R3+v4QoAyIgp6VUwt2b/CWbpqFWjykUlfdQ76td9 BF4FPcGDWoMCvpYNUO6QMCp5wDuH67q6XdyulFlWno04TAYTnxD6ej9OSIzogUvycEOP 1YMgSEJ5qvbmmZoe4mVrvv+IN9Vfv24jmoDZrNi2vfY8hGB4pEDMXwexqllwUGLHa1ap shtgJh23hPE4HZ6ZH6p+zU6pDAfm8rLJXufgWgqHyixYJFSQyTMuF5aK6Lf/Po7aOxNT CwzQ== X-Gm-Message-State: ABuFfogU7NF8RYYiR36mofW59UhQvmRbXGsUa5wB4WyB1wM2eXrKnKfI bHDkvqfYt/WmxYDSM4RoJlNC6q5u X-Google-Smtp-Source: ACcGV63+y0KISuapSMwm09wdequn6XFirqY2pT4v58I62jxqTREw0ncV03Dfn0EzIhRaztb4RgphVw== X-Received: by 2002:a24:7cc6:: with SMTP id a189-v6mr6238972itd.42.1538697493465; Thu, 04 Oct 2018 16:58:13 -0700 (PDT) Original-Received: from zebian (cbl-45-2-119-34.yyz.frontiernetworks.ca. [45.2.119.34]) by smtp.googlemail.com with ESMTPSA id m23-v6sm1983941ioj.46.2018.10.04.16.58.11 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 04 Oct 2018 16:58:12 -0700 (PDT) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:150947 Archived-At: --=-=-= Content-Type: text/plain Severity: wishlist As a followup from [1], here is a patchset which replaces the master's current rejection of confusable quotes on `read', and instead adds a hint to the error message when evaluating an expression with a confusable quote leads to an error. And also highlight such quotes with warning-face. [1]: https://lists.gnu.org/archive/html/emacs-devel/2018-02/msg00093.html --=-=-= Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename=v1-0001-Stop-signaling-an-error-when-reading-smart-quotes.patch Content-Transfer-Encoding: quoted-printable Content-Description: patch >From 330f6072c3dc614936199f1775679328c5452416 Mon Sep 17 00:00:00 2001 From: Noam Postavsky Date: Sat, 10 Mar 2018 18:20:45 -0500 Subject: [PATCH v1 1/2] Stop signaling an error when reading "smart quotes"= in symbols Revert commits from 2018-01-28 "Fix round tripping of read->print for symbols with strange quotes", and 2017-07-22 "Signal error for symbol names with strange quotes (Bug#2967)". * etc/NEWS: Remove corresponding entries. * src/character.c (confusable_symbol_character_p): * test/src/lread-tests.el (lread-tests--old-style-backquotes): Remove. * src/lread.c (read1): Don't signal error on confusable character. * src/print.c (print_object): Don't escape confusable characters. --- etc/NEWS | 9 --------- src/character.c | 26 -------------------------- src/character.h | 2 -- src/lread.c | 7 ------- src/print.c | 3 +-- test/src/lread-tests.el | 17 ----------------- 6 files changed, 1 insertion(+), 63 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index daacf49e62..1ca4956c96 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1073,15 +1073,6 @@ and if the new behavior breaks your code please email 32252@debbugs.gnu.org. Because %o and %x can now format signed integers, they now support the + and space flags. =20 -** To avoid confusion caused by "smart quotes", the reader signals an -error when reading Lisp symbols which begin with one of the following -quotation characters: =E2=80=98=E2=80=99=E2=80=9B=E2=80=9C=E2=80=9D=E2=80= =9F=E3=80=9E=EF=BC=82=EF=BC=87. A symbol beginning with such a -character can be written by escaping the quotation character with a -backslash. For example: - - (read "=E2=80=98smart") =3D> (invalid-read-syntax "strange quote" "=E2= =80=98") - (read "\\=E2=80=98smart") =3D=3D (intern "=E2=80=98smart") - +++ ** Omitting variables after '&optional' and '&rest' is now allowed. For example (defun foo (&optional)) is no longer an error. This is diff --git a/src/character.c b/src/character.c index 0b14e476c1..edaeca0a35 100644 --- a/src/character.c +++ b/src/character.c @@ -1056,32 +1056,6 @@ blankp (int c) return XFIXNUM (category) =3D=3D UNICODE_CATEGORY_Zs; /* separator, spac= e */ } =20 - -/* Return true for characters that would read as symbol characters, - but graphically may be confused with some kind of punctuation. We - require an escaping backslash, when such characters begin a - symbol. */ -bool -confusable_symbol_character_p (int ch) -{ - switch (ch) - { - case 0x2018: /* LEFT SINGLE QUOTATION MARK */ - case 0x2019: /* RIGHT SINGLE QUOTATION MARK */ - case 0x201B: /* SINGLE HIGH-REVERSED-9 QUOTATION MARK */ - case 0x201C: /* LEFT DOUBLE QUOTATION MARK */ - case 0x201D: /* RIGHT DOUBLE QUOTATION MARK */ - case 0x201F: /* DOUBLE HIGH-REVERSED-9 QUOTATION MARK */ - case 0x301E: /* DOUBLE PRIME QUOTATION MARK */ - case 0xFF02: /* FULLWIDTH QUOTATION MARK */ - case 0xFF07: /* FULLWIDTH APOSTROPHE */ - return true; - - default: - return false; - } -} - signed char HEXDIGIT_CONST hexdigit[UCHAR_MAX + 1] =3D { #if HEXDIGIT_IS_CONST diff --git a/src/character.h b/src/character.h index 5dff85aed4..6d5349e07d 100644 --- a/src/character.h +++ b/src/character.h @@ -683,8 +683,6 @@ char_surrogate_p (int c) extern bool printablep (int); extern bool blankp (int); =20 -extern bool confusable_symbol_character_p (int ch); - /* Return a translation table of id number ID. */ #define GET_TRANSLATION_TABLE(id) \ (XCDR (XVECTOR (Vtranslation_table_vector)->contents[(id)])) diff --git a/src/lread.c b/src/lread.c index 73e38d8995..fa3b38c312 100644 --- a/src/lread.c +++ b/src/lread.c @@ -3539,13 +3539,6 @@ read1 (Lisp_Object readcharfun, int *pch, bool first= _in_list) if (! NILP (result)) return unbind_to (count, result); } - if (!quoted && multibyte) - { - int ch =3D STRING_CHAR ((unsigned char *) read_buffer); - if (confusable_symbol_character_p (ch)) - xsignal2 (Qinvalid_read_syntax, build_string ("strange quote= "), - CALLN (Fstring, make_fixnum (ch))); - } { Lisp_Object result; ptrdiff_t nbytes =3D p - read_buffer; diff --git a/src/print.c b/src/print.c index c0c90bc7e9..c112d806cc 100644 --- a/src/print.c +++ b/src/print.c @@ -2049,8 +2049,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharf= un, bool escapeflag) || c =3D=3D ';' || c =3D=3D '#' || c =3D=3D '(' || c =3D=3D ')' || c =3D=3D ',' || c =3D=3D '.' || c =3D=3D '`' || c =3D=3D '[' || c =3D=3D ']' || c =3D=3D '?' || c <=3D 040 - || confusing - || (i =3D=3D 1 && confusable_symbol_character_p (c))) + || confusing) { printchar ('\\', printcharfun); confusing =3D false; diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el index f19d98320a..0d7cd962bd 100644 --- a/test/src/lread-tests.el +++ b/test/src/lread-tests.el @@ -142,23 +142,6 @@ lread-tests--last-message "unescaped character literals " "`?\"', `?(', `?)', `?;', `?[', `?]' detected!"= ))))) =20 -(ert-deftest lread-tests--funny-quote-symbols () - "Check that 'smart quotes' or similar trigger errors in symbol names." - (dolist (quote-char - '(#x2018 ;; LEFT SINGLE QUOTATION MARK - #x2019 ;; RIGHT SINGLE QUOTATION MARK - #x201B ;; SINGLE HIGH-REVERSED-9 QUOTATION MARK - #x201C ;; LEFT DOUBLE QUOTATION MARK - #x201D ;; RIGHT DOUBLE QUOTATION MARK - #x201F ;; DOUBLE HIGH-REVERSED-9 QUOTATION MARK - #x301E ;; DOUBLE PRIME QUOTATION MARK - #xFF02 ;; FULLWIDTH QUOTATION MARK - #xFF07 ;; FULLWIDTH APOSTROPHE - )) - (let ((str (format "%cfoo" quote-char))) - (should-error (read str) :type 'invalid-read-syntax) - (should (eq (read (concat "\\" str)) (intern str)))))) - (ert-deftest lread-test-bug26837 () "Test for https://debbugs.gnu.org/26837 ." (let ((load-path (cons --=20 2.11.0 --=-=-= Content-Type: text/plain Content-Disposition: attachment; filename=v1-0002-Give-suggestions-on-errors-about-var-names-with-c.patch Content-Description: patch >From d45f4f8aafb3caaf411d8bb5e434f42bc2d5f56a Mon Sep 17 00:00:00 2001 From: Noam Postavsky Date: Sat, 10 Mar 2018 18:12:55 -0500 Subject: [PATCH v1 2/2] Give suggestions on errors about var names with confusable chars Add some hints to the message for byte compiler 'free variable' warnings and 'void-variable' errors where the variable has confusable characters in it. * lisp/help.el (uni-confusables), uni-confusables-regexp): New constants. (help-command-error-confusable-suggestions): New function, added to `command-error-function'. (help-uni-confusable-suggestions): New function. * lisp/emacs-lisp/bytecomp.el (byte-compile-variable-ref): Use it. * lisp/emacs-lisp/lisp-mode.el (lisp--match-confusable-symbol-character): New function. (lisp-fdefs): Use it to fontify confusable characters with font-lock-warning-face when they occur in symbol names. --- lisp/emacs-lisp/bytecomp.el | 10 +++++++-- lisp/emacs-lisp/lisp-mode.el | 16 ++++++++++++++- lisp/help.el | 48 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 8b67e1007d..31d589ab02 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -3407,7 +3407,10 @@ byte-compile-variable-ref (boundp var) (memq var byte-compile-bound-variables) (memq var byte-compile-free-references)) - (byte-compile-warn "reference to free variable `%S'" var) + (let* ((varname (prin1-to-string var)) + (suggestions (help-uni-confusable-suggestions varname))) + (byte-compile-warn "reference to free variable `%s'%s" varname + (if suggestions (concat "\n " suggestions) ""))) (push var byte-compile-free-references)) (byte-compile-dynamic-variable-op 'byte-varref var)))) @@ -3423,7 +3426,10 @@ byte-compile-variable-set (boundp var) (memq var byte-compile-bound-variables) (memq var byte-compile-free-assignments)) - (byte-compile-warn "assignment to free variable `%s'" var) + (let* ((varname (prin1-to-string var)) + (suggestions (help-uni-confusable-suggestions varname))) + (byte-compile-warn "assignment to free variable `%s'%s" varname + (if suggestions (concat "\n " suggestions) ""))) (push var byte-compile-free-assignments)) (byte-compile-dynamic-variable-op 'byte-varset var)))) diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index f31b4d4dd2..87bdafa976 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -280,6 +280,17 @@ elisp--font-lock-backslash `(face ,font-lock-warning-face help-echo "This \\ has no effect")))) +(defun lisp--match-confusable-symbol-character (limit) + ;; Match a confusable character within a Lisp symbol. + (catch 'matched + (while t + (if (not (re-search-forward uni-confusables-regexp limit t)) + (throw 'matched nil) + ;; Skip confusables inside strings or comments. + (save-match-data + (if (not (nth 8 (syntax-ppss))) + (throw 'matched t))))))) + (let-when-compile ((lisp-fdefs '("defmacro" "defun")) (lisp-vdefs '("defvar")) @@ -463,7 +474,10 @@ elisp--font-lock-backslash (3 'font-lock-regexp-grouping-construct prepend)) (lisp--match-hidden-arg (0 '(face font-lock-warning-face - help-echo "Hidden behind deeper element; move to another line?"))) + help-echo "Hidden behind deeper element; move to another line?"))) + (lisp--match-confusable-symbol-character + 0 '(face font-lock-warning-face + help-echo "Confusable character")) )) "Gaudy level highlighting for Emacs Lisp mode.") diff --git a/lisp/help.el b/lisp/help.el index 6e06fc9e1c..66d191f863 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1489,6 +1489,54 @@ help--make-usage-docstring (help--docstring-quote (format "%S" (help--make-usage fn arglist))))) + +;; Just some quote-like characters for now. TODO: generate this stuff +;; from official Unicode data. +(defconst uni-confusables + '((#x2018 . "'") ;; LEFT SINGLE QUOTATION MARK + (#x2019 . "'") ;; RIGHT SINGLE QUOTATION MARK + (#x201B . "'") ;; SINGLE HIGH-REVERSED-9 QUOTATION MARK + (#x201C . "\"") ;; LEFT DOUBLE QUOTATION MARK + (#x201D . "\"") ;; RIGHT DOUBLE QUOTATION MARK + (#x201F . "\"") ;; DOUBLE HIGH-REVERSED-9 QUOTATION MARK + (#x301E . "\"") ;; DOUBLE PRIME QUOTATION MARK + (#xFF02 . "'") ;; FULLWIDTH QUOTATION MARK + (#xFF07 . "'") ;; FULLWIDTH APOSTROPHE + )) + +(defconst uni-confusables-regexp + (concat "[" (mapcar #'car uni-confusables) "]")) + +(defun help-uni-confusable-suggestions (string) + "Return a message describing confusables in STRING." + (let ((i 0) + (confusables nil)) + (while (setq i (string-match uni-confusables-regexp string i)) + (let ((replacement (alist-get (aref string i) uni-confusables))) + (push (aref string i) confusables) + (setq string (replace-match replacement t t string)) + (setq i (+ i (length replacement))))) + (when confusables + (format-message + (if (> (length confusables) 1) + "Found confusable characters: %s; perhaps you meant: `%s'?" + "Found confusable character: %s, perhaps you meant: `%s'?") + (mapconcat (lambda (c) (format-message "`%c'" c)) + confusables ", ") + string)))) + +(defun help-command-error-confusable-suggestions (data _context _signal) + (pcase data + (`(void-variable ,var) + (princ (concat "\n " (help-uni-confusable-suggestions + (symbol-name var))) + t)) + (_ nil))) + +(add-function :after command-error-function + #'help-command-error-confusable-suggestions) + + (provide 'help) ;;; help.el ends here -- 2.11.0 --=-=-=--