From: Paul Eggert <eggert@cs.ucla.edu>
To: 20545@debbugs.gnu.org
Cc: Artur Malabarba <bruce.connor.am@gmail.com>
Subject: bug#20545: New minor mode Electric Quote
Date: Tue, 26 May 2015 04:24:12 -0700 [thread overview]
Message-ID: <556457DC.5050301@cs.ucla.edu> (raw)
In-Reply-To: <554FEFFE.7000303@cs.ucla.edu>
[-- Attachment #1: Type: text/plain, Size: 700 bytes --]
Attached is a revised patch that should address the comments raised:
* The new minor mode is now disabled by default.
* The patch doesn't affect .dir-locals.el.
* The new minor mode is now (less ambitiously) called Electric Quote mode, not
Electric Punct mode.
* Electric Quote mode combines well with Electric Pair mode's pairings of ` and
', turning them into electric ‘ and ’. I did not implement the electric quote
pairing of “ and ”, as it would be trickier to add and anyway any such pairing
is considerably lower priority for Elisp.
Plus another issue I found while testing:
* Electric quoting is now inactive in buffers whose coding systems can't
represent curved quotes.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-New-minor-mode-Electric-Quote.patch --]
[-- Type: text/x-patch; name="0001-New-minor-mode-Electric-Quote.patch", Size: 12395 bytes --]
From f3f584027819837c26adc311a936e7a897c92f44 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 26 May 2015 03:53:50 -0700
Subject: [PATCH] New minor mode Electric Quote
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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 | 9 ++++
doc/emacs/text.texi | 38 +++++++++++++++
etc/NEWS | 2 +
lisp/electric.el | 109 +++++++++++++++++++++++++++++++++++++++++++
lisp/progmodes/elisp-mode.el | 3 +-
6 files changed, 166 insertions(+), 1 deletion(-)
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
+@t{“like 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..b4538db 100644
--- a/doc/emacs/modes.texi
+++ b/doc/emacs/modes.texi
@@ -200,6 +200,15 @@ 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
+@cindex Electric Quote mode
+@cindex mode, Electric Quote
+@findex electric-quote-mode
+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}.
+
+@item
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..f243095 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,43 @@ 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.
+@node Quotation Marks
+@section Quotation Marks
+@cindex Quotation marks
+@cindex Electric Quote mode
+@cindex mode, Electric Quote
+ 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
+@t{“like this”}. Typewriter quotes are simple and portable; curved
+quotes are unambiguous 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
+@t{``like this''} to double quotation marks @t{“like this”}. These
+conversions are suppressed in buffers whose coding systems cannot
+represent curved quote characters.
+
+ 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 non-@code{nil}, in
+programming-language comments if @code{electric-quote-comment} is
+non-@code{nil}, and in programming-language strings if
+@code{electric-quote-string} is non-@code{nil}. The default is
+@code{nil} for @code{electric-quote-string} and @code{t} for the other
+variables.
+
+ 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,
+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}).
+@xref{Inserting Text}.
+
@node Filling
@section Filling Text
@cindex filling text
diff --git a/etc/NEWS b/etc/NEWS
index 1cccc31..3c0b2cf 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..a1fd6e9 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -413,6 +413,115 @@ 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."
+ ;; (check-coding-systems-region "‘’“”" nil (list buffer-file-coding-system)))
+ (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 e06b920..22f66a9 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -231,7 +231,8 @@ Blank lines separate paragraphs. Semicolons start comments.
(lisp-mode-variables nil nil 'elisp)
(add-hook 'after-load-functions #'elisp--font-lock-flush-elisp-buffers)
(setq-local electric-pair-text-pairs
- (cons '(?\` . ?\') electric-pair-text-pairs))
+ `((?‘ . ?’) (?\` . ?\') ,@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)
--
2.1.0
next prev parent reply other threads:[~2015-05-26 11:24 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-10 23:55 bug#20545: New minor mode Electric Punct Paul Eggert
2015-05-11 15:00 ` Eli Zaretskii
2015-05-13 7:48 ` Paul Eggert
2015-05-13 13:10 ` Stefan Monnier
2015-05-13 14:49 ` Paul Eggert
2015-05-13 17:05 ` Eli Zaretskii
2015-05-14 3:52 ` Stefan Monnier
2015-05-14 14:54 ` Eli Zaretskii
2015-05-13 16:54 ` Eli Zaretskii
2015-05-13 16:38 ` Eli Zaretskii
2015-05-13 16:56 ` Paul Eggert
2015-05-13 17:16 ` Eli Zaretskii
2015-05-13 18:10 ` Eli Zaretskii
2015-05-14 6:32 ` Paul Eggert
2015-05-16 21:20 ` Paul Eggert
2015-05-17 14:33 ` Eli Zaretskii
2015-05-17 16:58 ` Paul Eggert
2015-05-17 19:04 ` Eli Zaretskii
2015-06-01 3:06 ` bug#20545: Transliterating curved to straight quotes in 8-bit environments Paul Eggert
2015-06-01 14:31 ` Eli Zaretskii
2015-05-11 15:57 ` bug#20545: New minor mode Electric Punct Stefan Monnier
2015-05-13 7:33 ` Paul Eggert
2015-05-11 16:48 ` Artur Malabarba
2015-05-26 11:24 ` Paul Eggert [this message]
2015-05-27 14:24 ` bug#20545: New minor mode Electric Quote Eli Zaretskii
2015-05-27 15:27 ` Paul Eggert
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=556457DC.5050301@cs.ucla.edu \
--to=eggert@cs.ucla.edu \
--cc=20545@debbugs.gnu.org \
--cc=bruce.connor.am@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.