summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Stephani <phst@google.com>2017-07-23 21:58:49 +0200
committerPhilipp Stephani <phst@google.com>2017-10-01 00:20:36 +0200
commitd247e1d30abcb77665f829ca98a5bdef69ff4bc3 (patch)
treedb9c7b1127eaa1860fbc586c8eace53ea4e3c4f2
parentd88a0f6554888643854ddb2c1f49b77b0bf8904c (diff)
downloademacs-d247e1d30abcb77665f829ca98a5bdef69ff4bc3.tar.gz
Electric quote mode: Conditionally replace " (Bug#24710)
* lisp/electric.el (electric-quote-replace-double): New user option. (electric-quote-post-self-insert-function): Use it. * test/lisp/electric-tests.el (electric-quote-replace-double-disabled) (electric-quote-replace-double-bob) (electric-quote-replace-double-bol) (electric-quote-replace-double-after-space) (electric-quote-replace-double-after-letter) (electric-quote-replace-double-after-paren): New unit tests. * doc/emacs/text.texi (Quotation Marks): Document 'electric-quote-replace-double'.
-rw-r--r--doc/emacs/text.texi7
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/electric.el25
-rw-r--r--test/lisp/electric-tests.el41
4 files changed, 74 insertions, 4 deletions
diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi
index 496b43ce1e3..5aa0c77d34c 100644
--- a/doc/emacs/text.texi
+++ b/doc/emacs/text.texi
@@ -443,6 +443,13 @@ non-@code{nil}, and in programming-language strings if
@code{nil} for @code{electric-quote-string} and @code{t} for the other
variables.
+@vindex electric-quote-replace-double
+ You can also set the option @code{electric-quote-replace-double} to
+a non-@code{nil} value. Then, typing @t{"} insert an appropriate
+curved double quote depending on context: @t{“} at the beginning of
+the buffer or after a line break, whitespace, opening parenthesis, or
+quote character, and @t{”} otherwise.
+
Electric Quote mode is disabled by default. To toggle it, type
@kbd{M-x electric-quote-mode}. To toggle it in a single buffer, use
@kbd{M-x electric-quote-local-mode}. To suppress it for a single use,
diff --git a/etc/NEWS b/etc/NEWS
index 8fbc354fc06..42c1b048169 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -42,6 +42,11 @@ When you add a new item, use the appropriate mark if you are sure it applies,
This controls how long Emacs will wait for updates to the graphical
state to take effect (making a frame visible, for example).
++++
+** The new user option 'electric-quote-replace-double' controls
+whether " is also replaced in 'electric-quote-mode'. If non-nil, " is
+replaced by a double typographic quote.
+
* Changes in Specialized Modes and Packages in Emacs 27.1
diff --git a/lisp/electric.el b/lisp/electric.el
index d7929945db2..65e36b7a63f 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -451,6 +451,14 @@ whitespace, opening parenthesis, or quote and leaves \\=` alone."
:version "26.1"
:type 'boolean :safe #'booleanp :group 'electricity)
+(defcustom electric-quote-replace-double nil
+ "Non-nil means to replace \" with an electric double quote.
+Emacs replaces \" with an opening double quote after a line
+break, whitespace, opening parenthesis, or quote, and with a
+closing double quote otherwise."
+ :version "26.1"
+ :type 'boolean :safe #'booleanp :group 'electricity)
+
(defvar electric-quote-inhibit-functions ()
"List of functions that should inhibit electric quoting.
When the variable `electric-quote-mode' is non-nil, Emacs will
@@ -467,7 +475,9 @@ This requotes when a quoting key is typed."
(when (and electric-quote-mode
(or (eq last-command-event ?\')
(and (not electric-quote-context-sensitive)
- (eq last-command-event ?\`)))
+ (eq last-command-event ?\`))
+ (and electric-quote-replace-double
+ (eq last-command-event ?\")))
(not (run-hook-with-args-until-success
'electric-quote-inhibit-functions))
(if (derived-mode-p 'text-mode)
@@ -488,7 +498,8 @@ This requotes when a quoting key is typed."
(save-excursion
(let ((backtick ?\`))
(if (or (eq last-command-event ?\`)
- (and electric-quote-context-sensitive
+ (and (or electric-quote-context-sensitive
+ electric-quote-replace-double)
(save-excursion
(backward-char)
(or (bobp) (bolp)
@@ -506,13 +517,19 @@ This requotes when a quoting key is typed."
(setq last-command-event q<<))
((search-backward (string backtick) (1- (point)) t)
(replace-match (string q<))
- (setq last-command-event q<)))
+ (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>))))))))))
+ (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 fc69919fbe1..7df2449b9eb 100644
--- a/test/lisp/electric-tests.el
+++ b/test/lisp/electric-tests.el
@@ -617,6 +617,12 @@ baz\"\""
:fixture-fn #'electric-quote-local-mode
:test-in-comments nil :test-in-strings nil)
+(define-electric-pair-test electric-quote-replace-double-disabled
+ "" "\"" :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)
@@ -638,6 +644,13 @@ baz\"\""
:bindings '((electric-quote-context-sensitive . t))
:test-in-comments nil :test-in-strings nil)
+(define-electric-pair-test electric-quote-replace-double-bob
+ "" "\"" :expected-string "“" :expected-point 2
+ :modes '(text-mode)
+ :fixture-fn #'electric-quote-local-mode
+ :bindings '((electric-quote-replace-double . 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)
@@ -652,6 +665,13 @@ baz\"\""
:bindings '((electric-quote-context-sensitive . t))
:test-in-comments nil :test-in-strings nil)
+(define-electric-pair-test electric-quote-replace-double-bol
+ "a\n" "--\"" :expected-string "a\n“" :expected-point 4
+ :modes '(text-mode)
+ :fixture-fn #'electric-quote-local-mode
+ :bindings '((electric-quote-replace-double . 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)
@@ -666,6 +686,13 @@ baz\"\""
:bindings '((electric-quote-context-sensitive . t))
:test-in-comments nil :test-in-strings nil)
+(define-electric-pair-test electric-quote-replace-double-after-space
+ " " "-\"" :expected-string " “" :expected-point 3
+ :modes '(text-mode)
+ :fixture-fn #'electric-quote-local-mode
+ :bindings '((electric-quote-replace-double . 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)
@@ -680,6 +707,13 @@ baz\"\""
:bindings '((electric-quote-context-sensitive . t))
:test-in-comments nil :test-in-strings nil)
+(define-electric-pair-test electric-quote-replace-double-after-letter
+ "a" "-\"" :expected-string "a”" :expected-point 3
+ :modes '(text-mode)
+ :fixture-fn #'electric-quote-local-mode
+ :bindings '((electric-quote-replace-double . 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)
@@ -694,6 +728,13 @@ baz\"\""
:bindings '((electric-quote-context-sensitive . t))
:test-in-comments nil :test-in-strings nil)
+(define-electric-pair-test electric-quote-replace-double-after-paren
+ "(" "-\"" :expected-string "(“" :expected-point 3
+ :modes '(text-mode)
+ :fixture-fn #'electric-quote-local-mode
+ :bindings '((electric-quote-replace-double . 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