emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 73512b8: New minor mode Electric Quote


From: Paul Eggert
Subject: [Emacs-diffs] master 73512b8: New minor mode Electric Quote
Date: Thu, 28 May 2015 07:54:11 +0000

branch: master
commit 73512b8cff21a5d92ca72b6cfa34a9210d5a5441
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    New minor mode Electric Quote
    
    This lets you easily insert quotes ‘like this’ by typing
    quotes `like this', and similarly you can easily insert
    quotes “like this” by typing quotes ``like this'' (Bug#20545).
    * doc/emacs/basic.texi (Inserting Text):
    * doc/emacs/modes.texi (Minor Modes):
    * etc/NEWS: Document it.
    * doc/emacs/text.texi (Quotation Marks): New section.
    * lisp/electric.el (electric-quote-comment)
    (electric-quote-string, electric-quote-paragraph):
    New custom vars.
    (electric--insertable-p)
    (electric-quote-post-self-insert-function): New functions.
    (electric-quote-mode, electric-quote-local-mode): New minor modes.
    * lisp/progmodes/elisp-mode.el (emacs-lisp-mode):
    Add curved single quotes to electric-pair-text-pairs.
    Set electric-quote-string in this buffer.
---
 doc/emacs/basic.texi         |    6 ++
 doc/emacs/modes.texi         |    6 ++
 doc/emacs/text.texi          |   42 ++++++++++++++++
 etc/NEWS                     |    2 +
 lisp/electric.el             |  108 ++++++++++++++++++++++++++++++++++++++++++
 lisp/progmodes/elisp-mode.el |    1 +
 6 files changed, 165 insertions(+), 0 deletions(-)

diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi
index be45856..cc9602e 100644
--- a/doc/emacs/basic.texi
+++ b/doc/emacs/basic.texi
@@ -127,6 +127,12 @@ sign (Unicode code-point @code{U+221E}):
   A numeric argument to @kbd{C-q} or @kbd{C-x 8 @key{RET}} specifies
 how many copies of the character to insert (@pxref{Arguments}).
 
+  In some contexts, if you type a quotation using grave accent and
+apostrophe @t{`like this'}, it is converted to a form @t{‘like this’}
+using single quotation marks.  Similarly, typing a quotation @t{``like
+this''} using double grave accent and apostrophe converts it to a form
address@hidden this”} using double quotation marks.  @xref{Quotation Marks}.
+
 @node Moving Point
 @section Changing the Location of Point
 
diff --git a/doc/emacs/modes.texi b/doc/emacs/modes.texi
index 0e8f46a..e79561a 100644
--- a/doc/emacs/modes.texi
+++ b/doc/emacs/modes.texi
@@ -200,6 +200,12 @@ Auto Save mode saves the buffer contents periodically to 
reduce the
 amount of work you can lose in case of a crash.  @xref{Auto Save}.
 
 @item
+Electric Quote mode automatically converts quotation marks.  For
+example, it requotes text typed @t{`like this'} to text @t{‘like
+this’}.  You can control what kind of text it operates in, and you can
+disable it entirely in individual buffers.  @xref{Quotation Marks}.
+
address@hidden
 Enriched mode enables editing and saving of formatted text.
 @xref{Enriched Text}.
 
diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi
index 9bc5ade..d891cc1 100644
--- a/doc/emacs/text.texi
+++ b/doc/emacs/text.texi
@@ -69,6 +69,7 @@ for editing such pictures.
 * Sentences::           Moving over and killing sentences.
 * Paragraphs::          Moving over paragraphs.
 * Pages::               Moving over pages.
+* Quotation Marks::     Inserting quotation marks.
 * Filling::             Filling or justifying text.
 * Case::                Changing the case of text.
 * Text Mode::           The major modes for editing text files.
@@ -404,6 +405,47 @@ that separates pages (@pxref{Regexps}).  The normal value 
of this
 variable is @code{"^\f"}, which matches a formfeed character at the
 beginning of a line.
 
address@hidden Quotation Marks
address@hidden Quotation Marks
address@hidden Quotation marks
address@hidden Electric Quote mode
address@hidden mode, Electric Quote
address@hidden electric-quote-mode
+  One common way to quote is the typewriter convention, which quotes
+using straight apostrophes @t{'like this'} or double-quotes @t{"like
+this"}.  Another common way is the curved quote convention, which uses
+left and right single or double quotation marks @t{‘like this’} or
address@hidden this”}.  Typewriter quotes are simple and portable; curved
+quotes are less ambiguous and typically look nicer.
+
+  Electric Quote mode makes it easier to type curved quotes.  It
+optionally converts a quotation's grave accent and apostrophe @t{`like
+this'} to single quotation marks @t{‘like this’}.  Similarly, it
+converts a quotation's double grave accent and double apostrophe
address@hidden this''} to double quotation marks @t{“like this”}.  These
+conversions are suppressed in buffers whose coding systems cannot
+represent curved quote characters.
+
address@hidden electric-quote-paragraph
address@hidden electric-quote-comment
address@hidden electric-quote-string
+  You can customize the behavior of Electric Quote mode by customizing
+variables that control where it is active.  It is active in text
+paragraphs if @code{electric-quote-paragraph} is address@hidden, in
+programming-language comments if @code{electric-quote-comment} is
address@hidden, and in programming-language strings if
address@hidden is address@hidden  The default is
address@hidden for @code{electric-quote-string} and @code{t} for the other
+variables.
+
+  Electric Quote mode is disabled by default.  To toggle it, type
address@hidden electric-quote-mode}.  To toggle it in a single buffer, use
address@hidden electric-quote-local-mode}.  To suppress it for a single use,
+type @kbd{C-q `} or @kbd{C-q '} instead of @kbd{`} or @kbd{'}.  To
+insert a curved quote even when Electric Quote is disabled or
+inactive, use @kbd{C-x 8 @key{RET}} (@code{insert-char}).
address@hidden Text}.
+
 @node Filling
 @section Filling Text
 @cindex filling text
diff --git a/etc/NEWS b/etc/NEWS
index 8fe9012..77953c8 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -226,6 +226,8 @@ successive char insertions.
 ** C-x 8 now has shorthands for these chars: ‐ ‑ ‒ – — ― ‘ ’ “ ” † ‡ • ′ ″
 € № ← → ↔ − ≈ ≠ ≤ ≥.  As before, you can type C-x 8 C-h to list shorthands.
 
+** New minor mode electric-quote-mode for quoting ‘like this’ and “like this”.
+
 ** New minor mode global-eldoc-mode is enabled by default.
 
 ** Emacs now supports "bracketed paste mode" when running on a terminal
diff --git a/lisp/electric.el b/lisp/electric.el
index dd7767f..88b2835 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -413,6 +413,114 @@ The variable `electric-layout-rules' says when and how to 
insert newlines."
          (remove-hook 'post-self-insert-hook
                       #'electric-layout-post-self-insert-function))))
 
+;;; Electric quoting.
+
+(defcustom electric-quote-comment t
+  "Non-nil means to use electric quoting in program comments."
+  :type 'boolean :safe 'booleanp :group 'electricity)
+
+(defcustom electric-quote-string nil
+  "Non-nil means to use electric quoting in program strings."
+  :type 'boolean :safe 'booleanp :group 'electricity)
+
+(defcustom electric-quote-paragraph t
+  "Non-nil means to use electric quoting in text paragraphs."
+  :type 'boolean :safe 'booleanp :group 'electricity)
+
+(defun electric--insertable-p (string)
+  (not (unencodable-char-position nil nil buffer-file-coding-system
+                                  nil string)))
+
+(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 '(?\' ?\`)))
+    (let ((start
+           (if comment-start
+               (when (or electric-quote-comment electric-quote-string)
+                 (let ((syntax (syntax-ppss)))
+                   (and (or (and electric-quote-comment (nth 4 syntax))
+                            (and electric-quote-string (nth 3 syntax)))
+                        (nth 8 syntax))))
+             (and electric-quote-paragraph
+                  (derived-mode-p 'text-mode)
+                  (or (eq last-command-event ?\`)
+                      (save-excursion (backward-paragraph) (point)))))))
+      (when start
+        (save-excursion
+          (if (eq last-command-event ?\`)
+              (cond ((and (electric--insertable-p "“")
+                          (re-search-backward "[`‘]`" (- (point) 2) t))
+                     (replace-match "“")
+                     (when (and electric-pair-mode
+                                (eq (cdr-safe
+                                     (assq ?‘ electric-pair-text-pairs))
+                                    (char-after)))
+                       (delete-char 1))
+                     (setq last-command-event ?“))
+                    ((and (electric--insertable-p "‘")
+                          (search-backward "`" (1- (point)) t))
+                     (replace-match "‘")
+                     (setq last-command-event ?‘)))
+            (let ((pos (point)))
+              (if (memq (char-before (1- (point))) '(?\' ?’))
+                  (when (and (search-backward "“" start t)
+                             (eq pos (re-search-forward
+                                      "“\\(\\([^‘”]\\|‘[^‘’”]*’\\)*\\)['’]'"
+                                      pos t)))
+                    (replace-match "“\\1”")
+                    (setq last-command-event ?”))
+                (when (and (search-backward "‘" start t)
+                           (eq pos (re-search-forward
+                                    "‘\\([^’]*\\)'" pos t)))
+                  (replace-match "‘\\1’")
+                  (setq last-command-event ?’))))))))))
+
+(put 'electric-quote-post-self-insert-function 'priority 10)
+
+;;;###autoload
+(define-minor-mode electric-quote-mode
+  "Toggle on-the-fly requoting (Electric Quote mode).
+With a prefix argument ARG, enable Electric Quote mode if
+ARG is positive, and disable it otherwise.  If called from Lisp,
+enable the mode if ARG is omitted or nil.
+
+When enabled, this replaces \\=`foo bar' with ‘foo bar’ and replaces
+\\=`\\=`foo bar'' with “foo bar” as you type.  This occurs only in
+comments, strings, and text paragraphs, and these are selectively
+controlled with ‘electric-quote-comment’,
+‘electric-quote-string’, and ‘electric-quote-paragraph’.
+
+This is a global minor mode.  To toggle the mode in a single buffer,
+use ‘electric-quote-local-mode’."
+  :global t :group 'electricity
+  :initialize 'custom-initialize-delay
+  :init-value nil
+  (if (not electric-quote-mode)
+      (unless (catch 'found
+                (dolist (buf (buffer-list))
+                  (with-current-buffer buf
+                    (if electric-quote-mode (throw 'found t)))))
+        (remove-hook 'post-self-insert-hook
+                     #'electric-quote-post-self-insert-function))
+    (add-hook 'post-self-insert-hook
+              #'electric-quote-post-self-insert-function)
+    (electric--sort-post-self-insertion-hook)))
+
+;;;###autoload
+(define-minor-mode electric-quote-local-mode
+  "Toggle ‘electric-quote-mode’ only in this buffer."
+  :variable (buffer-local-value 'electric-quote-mode (current-buffer))
+  (cond
+   ((eq electric-quote-mode (default-value 'electric-quote-mode))
+    (kill-local-variable 'electric-quote-mode))
+   ((not (default-value 'electric-quote-mode))
+    ;; Locally enabled, but globally disabled.
+    (electric-quote-mode 1)                ; Setup the hooks.
+    (setq-default electric-quote-mode nil) ; But keep it globally disabled.
+    )))
+
 (provide 'electric)
 
 ;;; electric.el ends here
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index b070029..bcbf1d5 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -232,6 +232,7 @@ Blank lines separate paragraphs.  Semicolons start comments.
   (add-hook 'after-load-functions #'elisp--font-lock-flush-elisp-buffers)
   (setq-local electric-pair-text-pairs
               (append '((?\` . ?\') (?‘ . ?’)) electric-pair-text-pairs))
+  (setq-local electric-quote-string t)
   (setq imenu-case-fold-search nil)
   (add-function :before-until (local 'eldoc-documentation-function)
                 #'elisp-eldoc-documentation-function)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]