* bug#24709: 26.0.50; Support for Markdown in electric-quote-mode @ 2016-10-16 17:19 Philipp Stephani 2016-10-19 11:10 ` Alan Third ` (2 more replies) 0 siblings, 3 replies; 7+ messages in thread From: Philipp Stephani @ 2016-10-16 17:19 UTC (permalink / raw) To: 24709 When editing a Markdown document with electric-quote-mode enabled, the experience is not optimal because ` (backtick) in Markdown is a syntax element (for introducing code spans and blocks), but is converted by electric-quote-mode. Also ` and ' inside code spans and blocks continue to insert curly quotes where they shouldn't. I propose the following: - Provide an alternative behavior of electric-quote-mode where ` doesn't trigger replacement and ' can insert left or right curly quotes, depending on whether it follows a space or similar (newline, beginning of buffer, opening parenthesis). - Provide a way to disable electric-quote-mode for certain regions, effectively the inverse of the existing electric-quote-string etc. This could be in the form of syntactic elements or text properties. In GNU Emacs 26.0.50.4 (x86_64-apple-darwin16.0.0, NS appkit-1504.00 Version 10.12 (Build 16A323)) of 2016-10-16 built on p Repository revision: cf566b46a6cf85c6d54d0b0db80e32ed6ae8d1ca Windowing system distributor 'Apple', version 10.3.1504 Recent messages: For information about GNU Emacs and the GNU system, type C-h C-a. Configured using: 'configure --with-modules --enable-checking --enable-check-lisp-object-type --without-xml2' Configured features: RSVG IMAGEMAGICK DBUS NOTIFY ACL GNUTLS ZLIB TOOLKIT_SCROLL_BARS NS MODULES Important settings: value of $LANG: de_DE.UTF-8 locale-coding-system: utf-8-unix Major mode: Lisp Interaction Minor modes in effect: tooltip-mode: t global-eldoc-mode: t electric-indent-mode: t mouse-wheel-mode: t tool-bar-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t blink-cursor-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t line-number-mode: t transient-mark-mode: t Load-path shadows: None found. Features: (shadow sort mail-extr emacsbug message subr-x puny seq byte-opt gv bytecomp byte-compile cl-extra help-mode cconv cl-loaddefs pcase cl-lib dired dired-loaddefs format-spec rfc822 mml easymenu mml-sec password-cache epa derived epg epg-config gnus-util rmail rmail-loaddefs mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils time-date mule-util tooltip eldoc electric uniquify ediff-hook vc-hooks lisp-float-type mwheel term/ns-win ns-win ucs-normalize term/common-win tool-bar dnd fontset image regexp-opt fringe tabulated-list newcomment elisp-mode lisp-mode prog-mode register page menu-bar rfn-eshadow timer select scroll-bar mouse jit-lock font-lock syntax facemenu font-core term/tty-colors frame cl-generic cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese charscript case-table epa-hook jka-cmpr-hook help simple abbrev obarray minibuffer cl-preloaded nadvice loaddefs button faces cus-face macroexp files text-properties overlay sha1 md5 base64 format env code-pages mule custom widget hashtable-print-readable backquote dbusbind kqueue cocoa ns multi-tty make-network-process emacs) Memory information: ((conses 16 206733 10576) (symbols 48 20333 0) (miscs 40 43 151) (strings 32 18363 6592) (string-bytes 1 593794) (vectors 16 35285) (vector-slots 8 676063 5565) (floats 8 183 55) (intervals 56 207 0) (buffers 976 11)) ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#24709: 26.0.50; Support for Markdown in electric-quote-mode 2016-10-16 17:19 bug#24709: 26.0.50; Support for Markdown in electric-quote-mode Philipp Stephani @ 2016-10-19 11:10 ` Alan Third 2017-06-28 21:59 ` Philipp Stephani 2017-07-14 12:36 ` Paul Eggert 2 siblings, 0 replies; 7+ messages in thread From: Alan Third @ 2016-10-19 11:10 UTC (permalink / raw) To: Philipp Stephani; +Cc: 24709 On Sun, Oct 16, 2016 at 07:19:12PM +0200, Philipp Stephani wrote: > - Provide an alternative behavior of electric-quote-mode where ` doesn't > trigger replacement and ' can insert left or right curly quotes, > depending on whether it follows a space or similar (newline, beginning > of buffer, opening parenthesis). I wrote a minor mode that does this, sort of. The defaults are probably not what you want, but it should be easy to modify: https://gist.github.com/alanthird/b758d3fb45b0e863f8a4 -- Alan Third ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#24709: 26.0.50; Support for Markdown in electric-quote-mode 2016-10-16 17:19 bug#24709: 26.0.50; Support for Markdown in electric-quote-mode Philipp Stephani 2016-10-19 11:10 ` Alan Third @ 2017-06-28 21:59 ` Philipp Stephani 2017-07-02 15:49 ` Philipp Stephani 2017-07-14 12:36 ` Paul Eggert 2 siblings, 1 reply; 7+ messages in thread From: Philipp Stephani @ 2017-06-28 21:59 UTC (permalink / raw) To: 24709 [-- Attachment #1.1: Type: text/plain, Size: 1053 bytes --] Philipp Stephani <p.stephani2@gmail.com> schrieb am So., 16. Okt. 2016 um 19:22 Uhr: > > When editing a Markdown document with electric-quote-mode enabled, the > experience is not optimal because ` (backtick) in Markdown is a syntax > element (for introducing code spans and blocks), but is converted by > electric-quote-mode. Also ` and ' inside code spans and blocks continue > to insert curly quotes where they shouldn't. I propose the following: > > - Provide an alternative behavior of electric-quote-mode where ` doesn't > trigger replacement and ' can insert left or right curly quotes, > depending on whether it follows a space or similar (newline, beginning > of buffer, opening parenthesis). > > - Provide a way to disable electric-quote-mode for certain regions, > effectively the inverse of the existing electric-quote-string etc. > This could be in the form of syntactic elements or text properties. > > > I've attached a patch. It doesn't cover all cases, though; e.g. an unterminated Markdown code span is not supported yet. [-- Attachment #1.2: Type: text/html, Size: 1411 bytes --] [-- Attachment #2: 0001-Electric-quotes-Improve-support-for-Markdown-mode-Bug-.txt --] [-- Type: text/plain, Size: 13187 bytes --] From 126557c6998950c522baab9d344bb62629b7f9c0 Mon Sep 17 00:00:00 2001 From: Philipp Stephani <phst@google.com> Date: Wed, 28 Jun 2017 23:47:57 +0200 Subject: [PATCH] Electric quotes: Improve support for Markdown mode (Bug#24709) Introduce a new user option 'electric-quote-context-sensitive'. If non-nil, have ' insert an opening quote if sensible. Also introduce a new variable 'electric-quote-code-faces'. Major modes such as 'markdown-mode' can add faces to this list to treat text as inline code and disable electric quoting. * lisp/electric.el (electric-quote-context-sensitive): New user option. (electric-quote-code-faces): New variable. (electric-quote-post-self-insert-function): Treat ' as ` if desired and applicable; disable electric quoting for given faces. * test/lisp/electric-tests.el (electric-quote-opening-single) (electric-quote-closing-single, electric-quote-opening-double) (electric-quote-closing-double) (electric-quote-context-sensitive-backtick) (electric-quote-context-sensitive-bob-single) (electric-quote-context-sensitive-bob-double) (electric-quote-context-sensitive-bol-single) (electric-quote-context-sensitive-bol-double) (electric-quote-context-sensitive-after-space-single) (electric-quote-context-sensitive-after-space-double) (electric-quote-context-sensitive-after-letter-single) (electric-quote-context-sensitive-after-letter-double) (electric-quote-context-sensitive-after-paren-single) (electric-quote-context-sensitive-after-paren-double) (electric-quote-markdown-in-text) (electric-quote-markdown-in-code): New unit tests. --- etc/NEWS | 16 ++++++ lisp/electric.el | 66 +++++++++++++++++-------- test/lisp/electric-tests.el | 116 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 19 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 5e10ca9cb6..b0bb5e1465 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -129,6 +129,22 @@ given file is on a case-insensitive filesystem. of curved quotes for 'electric-quote-mode', allowing user to choose the types of quotes to be used. +** The new user option 'electric-quote-context-sensitive' makes +'electric-quote-mode' context sensitive. If it is non-nil, you can +type an ASCII apostrophe to insert an opening or closing quote, +depending on context. Emacs will replace the apostrophe by an opening +quote character at the beginning of the buffer, the beginning of a +line, after a whitespace character, and after an opening parenthesis; +and it will replace the apostrophe by a closing quote character in all +other cases. + +** The new variable 'electric-quote-code-faces' controls when to +disable electric quoting in text modes. Major modes can add faces to +this list; Emacs will temporarily disable 'electric-quote-mode' +whenever point is before a character having such a face. This is +intended for major modes that derive from 'text-mode' but allow inline +code segments, such as 'markdown-mode'. + +++ ** The new user variable 'dired-omit-case-fold' allows the user to customize the case-sensitivity of dired-omit-mode. It defaults to diff --git a/lisp/electric.el b/lisp/electric.el index 4078ef8193..1564df5949 100644 --- a/lisp/electric.el +++ b/lisp/electric.el @@ -443,11 +443,24 @@ electric-quote-paragraph :version "25.1" :type 'boolean :safe 'booleanp :group 'electricity) +(defcustom electric-quote-context-sensitive nil + "Non-nil means to replace \\=' with an electric quote depending on context. +If `electric-quote-context-sensitive' is non-nil, Emacs replaces +\\=' and \\='\\=' with an opening quote after a line break, +whitespace, opening parenthesis, or quote and leaves \\=` alone." + :version "26.1" + :type 'boolean :safe #'booleanp :group 'electricity) + +(defvar electric-quote-code-faces () + "List of faces to treat as inline code in `text-mode'.") + (defun electric-quote-post-self-insert-function () "Function that `electric-quote-mode' adds to `post-self-insert-hook'. This requotes when a quoting key is typed." (when (and electric-quote-mode - (memq last-command-event '(?\' ?\`))) + (or (eq last-command-event ?\') + (and (not electric-quote-context-sensitive) + (eq last-command-event ?\`)))) (let ((start (if (and comment-start comment-use-syntax) (when (or electric-quote-comment electric-quote-string) @@ -462,30 +475,45 @@ electric-quote-post-self-insert-function (syntax-ppss (1- (point))))))))) (and electric-quote-paragraph (derived-mode-p 'text-mode) + ;; FIXME: There should be a ‘cl-disjoint’ function. + (null (cl-intersection (face-at-point nil 'multiple) + electric-quote-code-faces + :test #'eq)) + ;; FIXME: Why is the next form there? It’s never + ;; nil. (or (eq last-command-event ?\`) (save-excursion (backward-paragraph) (point))))))) (pcase electric-quote-chars (`(,q< ,q> ,q<< ,q>>) (when start (save-excursion - (if (eq last-command-event ?\`) - (cond ((search-backward (string q< ?`) (- (point) 2) t) - (replace-match (string q<<)) - (when (and electric-pair-mode - (eq (cdr-safe - (assq q< electric-pair-text-pairs)) - (char-after))) - (delete-char 1)) - (setq last-command-event q<<)) - ((search-backward "`" (1- (point)) t) - (replace-match (string q<)) - (setq last-command-event q<))) - (cond ((search-backward (string q> ?') (- (point) 2) t) - (replace-match (string q>>)) - (setq last-command-event q>>)) - ((search-backward "'" (1- (point)) t) - (replace-match (string q>)) - (setq last-command-event q>))))))))))) + (let ((backtick ?\`)) + (if (or (eq last-command-event ?\`) + (and electric-quote-context-sensitive + (save-excursion + (backward-char) + (or (bobp) (bolp) + (memq (char-before) (list q< q<<)) + (memq (char-syntax (char-before)) + '(?\s ?\()))) + (setq backtick ?\'))) + (cond ((search-backward (string q< backtick) (- (point) 2) t) + (replace-match (string q<<)) + (when (and electric-pair-mode + (eq (cdr-safe + (assq q< electric-pair-text-pairs)) + (char-after))) + (delete-char 1)) + (setq last-command-event q<<)) + ((search-backward (string backtick) (1- (point)) t) + (replace-match (string q<)) + (setq last-command-event q<))) + (cond ((search-backward (string q> ?') (- (point) 2) t) + (replace-match (string q>>)) + (setq last-command-event q>>)) + ((search-backward "'" (1- (point)) t) + (replace-match (string q>)) + (setq last-command-event q>)))))))))))) (put 'electric-quote-post-self-insert-function 'priority 10) diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el index 78a3765061..6f63d30e75 100644 --- a/test/lisp/electric-tests.el +++ b/test/lisp/electric-tests.el @@ -593,5 +593,121 @@ electric-quote-string :bindings '((electric-quote-string . t)) :test-in-comments nil :test-in-strings nil) +(define-electric-pair-test electric-quote-opening-single + "" "`" :expected-string "‘" :expected-point 2 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-closing-single + "" "'" :expected-string "’" :expected-point 2 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-opening-double + "‘" "-`" :expected-string "“" :expected-point 2 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-closing-double + "’" "-'" :expected-string "”" :expected-point 2 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-context-sensitive-backtick + "" "`" :expected-string "`" :expected-point 2 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-context-sensitive . t)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-context-sensitive-bob-single + "" "'" :expected-string "‘" :expected-point 2 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-context-sensitive . t)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-context-sensitive-bob-double + "‘" "-'" :expected-string "“" :expected-point 2 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-context-sensitive . t)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-context-sensitive-bol-single + "a\n" "--'" :expected-string "a\n‘" :expected-point 4 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-context-sensitive . t)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-context-sensitive-bol-double + "a\n‘" "---'" :expected-string "a\n“" :expected-point 4 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-context-sensitive . t)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-context-sensitive-after-space-single + " " "-'" :expected-string " ‘" :expected-point 3 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-context-sensitive . t)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-context-sensitive-after-space-double + " ‘" "--'" :expected-string " “" :expected-point 3 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-context-sensitive . t)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-context-sensitive-after-letter-single + "a" "-'" :expected-string "a’" :expected-point 3 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-context-sensitive . t)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-context-sensitive-after-letter-double + "a’" "--'" :expected-string "a”" :expected-point 3 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-context-sensitive . t)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-context-sensitive-after-paren-single + "(" "-'" :expected-string "(‘" :expected-point 3 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-context-sensitive . t)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-context-sensitive-after-paren-double + "(‘" "--'" :expected-string "(“" :expected-point 3 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-context-sensitive . t)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-markdown-in-text + "" "'" :expected-string "’" :expected-point 2 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-code-faces font-lock-constant-face)) + :test-in-comments nil :test-in-strings nil) + +(define-electric-pair-test electric-quote-markdown-in-code + #("`a`" 1 2 (face font-lock-constant-face)) "-'" + :expected-string "`'a`" :expected-point 3 + :modes '(text-mode) + :fixture-fn #'electric-quote-local-mode + :bindings '((electric-quote-code-faces font-lock-constant-face)) + :test-in-comments nil :test-in-strings nil) + (provide 'electric-tests) ;;; electric-tests.el ends here -- 2.13.2 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* bug#24709: 26.0.50; Support for Markdown in electric-quote-mode 2017-06-28 21:59 ` Philipp Stephani @ 2017-07-02 15:49 ` Philipp Stephani 2017-07-02 16:20 ` Philipp Stephani 0 siblings, 1 reply; 7+ messages in thread From: Philipp Stephani @ 2017-07-02 15:49 UTC (permalink / raw) To: 24709 [-- Attachment #1: Type: text/plain, Size: 1191 bytes --] Philipp Stephani <p.stephani2@gmail.com> schrieb am Mi., 28. Juni 2017 um 23:59 Uhr: > Philipp Stephani <p.stephani2@gmail.com> schrieb am So., 16. Okt. 2016 um > 19:22 Uhr: > >> >> When editing a Markdown document with electric-quote-mode enabled, the >> experience is not optimal because ` (backtick) in Markdown is a syntax >> element (for introducing code spans and blocks), but is converted by >> electric-quote-mode. Also ` and ' inside code spans and blocks continue >> to insert curly quotes where they shouldn't. I propose the following: >> >> - Provide an alternative behavior of electric-quote-mode where ` doesn't >> trigger replacement and ' can insert left or right curly quotes, >> depending on whether it follows a space or similar (newline, beginning >> of buffer, opening parenthesis). >> >> - Provide a way to disable electric-quote-mode for certain regions, >> effectively the inverse of the existing electric-quote-string etc. >> This could be in the form of syntactic elements or text properties. >> >> >> > I've attached a patch. It doesn't cover all cases, though; e.g. an > unterminated Markdown code span is not supported yet. > Pushed as 34d4720f83. [-- Attachment #2: Type: text/html, Size: 1866 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#24709: 26.0.50; Support for Markdown in electric-quote-mode 2017-07-02 15:49 ` Philipp Stephani @ 2017-07-02 16:20 ` Philipp Stephani 2017-07-09 19:57 ` Philipp Stephani 0 siblings, 1 reply; 7+ messages in thread From: Philipp Stephani @ 2017-07-02 16:20 UTC (permalink / raw) To: 24709 [-- Attachment #1.1: Type: text/plain, Size: 1343 bytes --] Philipp Stephani <p.stephani2@gmail.com> schrieb am So., 2. Juli 2017 um 17:49 Uhr: > Philipp Stephani <p.stephani2@gmail.com> schrieb am Mi., 28. Juni 2017 um > 23:59 Uhr: > >> Philipp Stephani <p.stephani2@gmail.com> schrieb am So., 16. Okt. 2016 >> um 19:22 Uhr: >> >>> >>> When editing a Markdown document with electric-quote-mode enabled, the >>> experience is not optimal because ` (backtick) in Markdown is a syntax >>> element (for introducing code spans and blocks), but is converted by >>> electric-quote-mode. Also ` and ' inside code spans and blocks continue >>> to insert curly quotes where they shouldn't. I propose the following: >>> >>> - Provide an alternative behavior of electric-quote-mode where ` doesn't >>> trigger replacement and ' can insert left or right curly quotes, >>> depending on whether it follows a space or similar (newline, beginning >>> of buffer, opening parenthesis). >>> >>> - Provide a way to disable electric-quote-mode for certain regions, >>> effectively the inverse of the existing electric-quote-string etc. >>> This could be in the form of syntactic elements or text properties. >>> >>> >>> >> I've attached a patch. It doesn't cover all cases, though; e.g. an >> unterminated Markdown code span is not supported yet. >> > > Pushed as 34d4720f83. > Here are a couple more patches. [-- Attachment #1.2: Type: text/html, Size: 2306 bytes --] [-- Attachment #2: 0001-Refactor-electric-quote-mode.txt --] [-- Type: text/plain, Size: 6763 bytes --] From 7d9439e3096a37ba381a9fd03d63d1b5fcf4683a Mon Sep 17 00:00:00 2001 From: Philipp Stephani <phst@google.com> Date: Sun, 2 Jul 2017 18:03:06 +0200 Subject: [PATCH 1/3] Refactor 'electric-quote-mode' * lisp/electric.el (electric-quote-post-self-insert-function): Remove local variable 'start', which was misnamed and only used once. --- lisp/electric.el | 106 +++++++++++++++++++++++++++---------------------------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/lisp/electric.el b/lisp/electric.el index 1564df5949..103f378ed3 100644 --- a/lisp/electric.el +++ b/lisp/electric.el @@ -460,60 +460,58 @@ electric-quote-post-self-insert-function (when (and electric-quote-mode (or (eq last-command-event ?\') (and (not electric-quote-context-sensitive) - (eq last-command-event ?\`)))) - (let ((start - (if (and comment-start comment-use-syntax) - (when (or electric-quote-comment electric-quote-string) - (let* ((syntax (syntax-ppss)) - (beg (nth 8 syntax))) - (and beg - (or (and electric-quote-comment (nth 4 syntax)) - (and electric-quote-string (nth 3 syntax))) - ;; Do not requote a quote that starts or ends - ;; a comment or string. - (eq beg (nth 8 (save-excursion - (syntax-ppss (1- (point))))))))) - (and electric-quote-paragraph - (derived-mode-p 'text-mode) - ;; FIXME: There should be a ‘cl-disjoint’ function. - (null (cl-intersection (face-at-point nil 'multiple) - electric-quote-code-faces - :test #'eq)) - ;; FIXME: Why is the next form there? It’s never - ;; nil. - (or (eq last-command-event ?\`) - (save-excursion (backward-paragraph) (point))))))) - (pcase electric-quote-chars - (`(,q< ,q> ,q<< ,q>>) - (when start - (save-excursion - (let ((backtick ?\`)) - (if (or (eq last-command-event ?\`) - (and electric-quote-context-sensitive - (save-excursion - (backward-char) - (or (bobp) (bolp) - (memq (char-before) (list q< q<<)) - (memq (char-syntax (char-before)) - '(?\s ?\()))) - (setq backtick ?\'))) - (cond ((search-backward (string q< backtick) (- (point) 2) t) - (replace-match (string q<<)) - (when (and electric-pair-mode - (eq (cdr-safe - (assq q< electric-pair-text-pairs)) - (char-after))) - (delete-char 1)) - (setq last-command-event q<<)) - ((search-backward (string backtick) (1- (point)) t) - (replace-match (string q<)) - (setq last-command-event q<))) - (cond ((search-backward (string q> ?') (- (point) 2) t) - (replace-match (string q>>)) - (setq last-command-event q>>)) - ((search-backward "'" (1- (point)) t) - (replace-match (string q>)) - (setq last-command-event q>)))))))))))) + (eq last-command-event ?\`))) + (if (and comment-start comment-use-syntax) + (when (or electric-quote-comment electric-quote-string) + (let* ((syntax (syntax-ppss)) + (beg (nth 8 syntax))) + (and beg + (or (and electric-quote-comment (nth 4 syntax)) + (and electric-quote-string (nth 3 syntax))) + ;; Do not requote a quote that starts or ends + ;; a comment or string. + (eq beg (nth 8 (save-excursion + (syntax-ppss (1- (point))))))))) + (and electric-quote-paragraph + (derived-mode-p 'text-mode) + ;; FIXME: There should be a ‘cl-disjoint’ function. + (null (cl-intersection (face-at-point nil 'multiple) + electric-quote-code-faces + :test #'eq)) + ;; FIXME: Why is the next form there? It’s never + ;; nil. + (or (eq last-command-event ?\`) + (save-excursion (backward-paragraph) (point)))))) + (pcase electric-quote-chars + (`(,q< ,q> ,q<< ,q>>) + (save-excursion + (let ((backtick ?\`)) + (if (or (eq last-command-event ?\`) + (and electric-quote-context-sensitive + (save-excursion + (backward-char) + (or (bobp) (bolp) + (memq (char-before) (list q< q<<)) + (memq (char-syntax (char-before)) + '(?\s ?\()))) + (setq backtick ?\'))) + (cond ((search-backward (string q< backtick) (- (point) 2) t) + (replace-match (string q<<)) + (when (and electric-pair-mode + (eq (cdr-safe + (assq q< electric-pair-text-pairs)) + (char-after))) + (delete-char 1)) + (setq last-command-event q<<)) + ((search-backward (string backtick) (1- (point)) t) + (replace-match (string q<)) + (setq last-command-event q<))) + (cond ((search-backward (string q> ?') (- (point) 2) t) + (replace-match (string q>>)) + (setq last-command-event q>>)) + ((search-backward "'" (1- (point)) t) + (replace-match (string q>)) + (setq last-command-event q>)))))))))) (put 'electric-quote-post-self-insert-function 'priority 10) -- 2.13.2 [-- Attachment #3: 0003-Further-improve-electric-quote-support-for-Markdown-Bu.txt --] [-- Type: text/plain, Size: 4844 bytes --] From 1a4d0ada2450f22246ad22d25e7c15d8da3c5249 Mon Sep 17 00:00:00 2001 From: Philipp Stephani <phst@google.com> Date: Sun, 2 Jul 2017 18:14:21 +0200 Subject: [PATCH 3/3] Further improve electric quote support for Markdown (Bug#24709) Markdown sets both 'comment-start' and 'comment-use-syntax' to non-nil values. Therefore 'electric-quote-mode' recognized it as a programming mode. Fix this by first checking whether the current major mode is derived from 'text-mode'. * lisp/electric.el (electric-quote-post-self-insert-function): Treat 'text-mode' as stronger signal than comment syntax. * test/lisp/electric-tests.el (electric-quote-markdown-in-text) (electric-quote-markdown-in-code): Adapt unit tests. --- lisp/electric.el | 34 +++++++++++++++++----------------- test/lisp/electric-tests.el | 8 ++++++-- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/lisp/electric.el b/lisp/electric.el index a1e9079cb1..c335ae5d72 100644 --- a/lisp/electric.el +++ b/lisp/electric.el @@ -461,23 +461,23 @@ electric-quote-post-self-insert-function (or (eq last-command-event ?\') (and (not electric-quote-context-sensitive) (eq last-command-event ?\`))) - (if (and comment-start comment-use-syntax) - (when (or electric-quote-comment electric-quote-string) - (let* ((syntax (syntax-ppss)) - (beg (nth 8 syntax))) - (and beg - (or (and electric-quote-comment (nth 4 syntax)) - (and electric-quote-string (nth 3 syntax))) - ;; Do not requote a quote that starts or ends - ;; a comment or string. - (eq beg (nth 8 (save-excursion - (syntax-ppss (1- (point))))))))) - (and electric-quote-paragraph - (derived-mode-p 'text-mode) - ;; FIXME: There should be a ‘cl-disjoint’ function. - (null (cl-intersection (face-at-point nil 'multiple) - electric-quote-code-faces - :test #'eq))))) + (if (derived-mode-p 'text-mode) + (and electric-quote-paragraph + ;; FIXME: There should be a ‘cl-disjoint’ function. + (null (cl-intersection (face-at-point nil 'multiple) + electric-quote-code-faces + :test #'eq))) + (and comment-start comment-use-syntax + (or electric-quote-comment electric-quote-string) + (let* ((syntax (syntax-ppss)) + (beg (nth 8 syntax))) + (and beg + (or (and electric-quote-comment (nth 4 syntax)) + (and electric-quote-string (nth 3 syntax))) + ;; Do not requote a quote that starts or ends + ;; a comment or string. + (eq beg (nth 8 (save-excursion + (syntax-ppss (1- (point))))))))))) (pcase electric-quote-chars (`(,q< ,q> ,q<< ,q>>) (save-excursion diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el index 6f63d30e75..4212198b0a 100644 --- a/test/lisp/electric-tests.el +++ b/test/lisp/electric-tests.el @@ -694,11 +694,14 @@ electric-quote-context-sensitive-after-paren-double :bindings '((electric-quote-context-sensitive . t)) :test-in-comments nil :test-in-strings nil) +;; Simulate ‘markdown-mode’: it sets both ‘comment-start’ and +;; ‘comment-use-syntax’, but derives from ‘text-mode’. (define-electric-pair-test electric-quote-markdown-in-text "" "'" :expected-string "’" :expected-point 2 :modes '(text-mode) :fixture-fn #'electric-quote-local-mode - :bindings '((electric-quote-code-faces font-lock-constant-face)) + :bindings '((electric-quote-code-faces font-lock-constant-face) + (comment-start "<!--") (comment-use-syntax t)) :test-in-comments nil :test-in-strings nil) (define-electric-pair-test electric-quote-markdown-in-code @@ -706,7 +709,8 @@ electric-quote-markdown-in-code :expected-string "`'a`" :expected-point 3 :modes '(text-mode) :fixture-fn #'electric-quote-local-mode - :bindings '((electric-quote-code-faces font-lock-constant-face)) + :bindings '((electric-quote-code-faces font-lock-constant-face) + (comment-start "<!--") (comment-use-syntax t)) :test-in-comments nil :test-in-strings nil) (provide 'electric-tests) -- 2.13.2 [-- Attachment #4: 0002-Remove-pointless-code-in-electric-quote-mode.txt --] [-- Type: text/plain, Size: 1245 bytes --] From 0acddd26f1bdb9b08dea9812af2883925e023557 Mon Sep 17 00:00:00 2001 From: Philipp Stephani <phst@google.com> Date: Sun, 2 Jul 2017 18:04:38 +0200 Subject: [PATCH 2/3] Remove pointless code in 'electric-quote-mode' * lisp/electric.el (electric-quote-post-self-insert-function): Remove pointless form. --- lisp/electric.el | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lisp/electric.el b/lisp/electric.el index 103f378ed3..a1e9079cb1 100644 --- a/lisp/electric.el +++ b/lisp/electric.el @@ -477,11 +477,7 @@ electric-quote-post-self-insert-function ;; FIXME: There should be a ‘cl-disjoint’ function. (null (cl-intersection (face-at-point nil 'multiple) electric-quote-code-faces - :test #'eq)) - ;; FIXME: Why is the next form there? It’s never - ;; nil. - (or (eq last-command-event ?\`) - (save-excursion (backward-paragraph) (point)))))) + :test #'eq))))) (pcase electric-quote-chars (`(,q< ,q> ,q<< ,q>>) (save-excursion -- 2.13.2 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* bug#24709: 26.0.50; Support for Markdown in electric-quote-mode 2017-07-02 16:20 ` Philipp Stephani @ 2017-07-09 19:57 ` Philipp Stephani 0 siblings, 0 replies; 7+ messages in thread From: Philipp Stephani @ 2017-07-09 19:57 UTC (permalink / raw) To: 24709 [-- Attachment #1: Type: text/plain, Size: 1481 bytes --] Philipp Stephani <p.stephani2@gmail.com> schrieb am So., 2. Juli 2017 um 18:19 Uhr: > Philipp Stephani <p.stephani2@gmail.com> schrieb am So., 2. Juli 2017 um > 17:49 Uhr: > >> Philipp Stephani <p.stephani2@gmail.com> schrieb am Mi., 28. Juni 2017 >> um 23:59 Uhr: >> >>> Philipp Stephani <p.stephani2@gmail.com> schrieb am So., 16. Okt. 2016 >>> um 19:22 Uhr: >>> >>>> >>>> When editing a Markdown document with electric-quote-mode enabled, the >>>> experience is not optimal because ` (backtick) in Markdown is a syntax >>>> element (for introducing code spans and blocks), but is converted by >>>> electric-quote-mode. Also ` and ' inside code spans and blocks continue >>>> to insert curly quotes where they shouldn't. I propose the following: >>>> >>>> - Provide an alternative behavior of electric-quote-mode where ` doesn't >>>> trigger replacement and ' can insert left or right curly quotes, >>>> depending on whether it follows a space or similar (newline, beginning >>>> of buffer, opening parenthesis). >>>> >>>> - Provide a way to disable electric-quote-mode for certain regions, >>>> effectively the inverse of the existing electric-quote-string etc. >>>> This could be in the form of syntactic elements or text properties. >>>> >>>> >>>> >>> I've attached a patch. It doesn't cover all cases, though; e.g. an >>> unterminated Markdown code span is not supported yet. >>> >> >> Pushed as 34d4720f83. >> > > Here are a couple more patches. > All pushed. [-- Attachment #2: Type: text/html, Size: 2738 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* bug#24709: 26.0.50; Support for Markdown in electric-quote-mode 2016-10-16 17:19 bug#24709: 26.0.50; Support for Markdown in electric-quote-mode Philipp Stephani 2016-10-19 11:10 ` Alan Third 2017-06-28 21:59 ` Philipp Stephani @ 2017-07-14 12:36 ` Paul Eggert 2 siblings, 0 replies; 7+ messages in thread From: Paul Eggert @ 2017-07-14 12:36 UTC (permalink / raw) To: Philipp Stephani; +Cc: 24709-done As the bug appears to be fixed, I'm taking the liberty of closing the bug report. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-07-14 12:36 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-10-16 17:19 bug#24709: 26.0.50; Support for Markdown in electric-quote-mode Philipp Stephani 2016-10-19 11:10 ` Alan Third 2017-06-28 21:59 ` Philipp Stephani 2017-07-02 15:49 ` Philipp Stephani 2017-07-02 16:20 ` Philipp Stephani 2017-07-09 19:57 ` Philipp Stephani 2017-07-14 12:36 ` Paul Eggert
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).