diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2015-05-28 00:46:59 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2015-05-28 00:54:06 -0700 |
commit | 73512b8cff21a5d92ca72b6cfa34a9210d5a5441 (patch) | |
tree | ca007c5cb2d83a984d2991b62a81c908e25596df /lisp/electric.el | |
parent | 4643f6c21a88d27cfb8a3410494bfd7909a98462 (diff) | |
download | emacs-73512b8cff21a5d92ca72b6cfa34a9210d5a5441.tar.gz |
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.
Diffstat (limited to 'lisp/electric.el')
-rw-r--r-- | lisp/electric.el | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/lisp/electric.el b/lisp/electric.el index dd7767fd5eb..88b28352ac0 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 |