Support for U+2018 LEFT SINGLE QUOTATION MARK and friends seems pretty widespread these days, so I think it’s time for this:
;;; smart-quotes.el --- Smart Quotes mode for Emacs ;; Copyright (C) 2007 Gareth Rees ;; Author: Gareth Rees <email@example.com> ;; Created: ;; Version: 1.1 ;; Keywords: abbrev ;; Smart Quotes mode is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation; either version 2, or (at ;; your option) any later version. ;;; Commentary: ;; In Smart Quotes minor mode, the ' and \" keys insert left and ;; right quotation marks according to the context around point. ;;; Code: (defcustom smart-quotes-left-context "^\\|\\s-\\|\\s(" "Regular expression matching the context in which a left quotation mark will be inserted (a right quotation mark will be inserted in all other contexts)." :type 'regexp) (defun smart-quotes-insert-single () "Insert U+2018 LEFT SINGLE QUOTATION MARK if point is preceded by `smart-quotes-left-context'; U+2019 RIGHT SINGLE QUOTATION MARK otherwise." (interactive) (ucs-insert (if (looking-back smart-quotes-left-context) #x2018 #x2019))) (defun smart-quotes-insert-double () "Insert U+201C LEFT DOUBLE QUOTATION MARK if point is preceded by `smart-quotes-left-context'; U+201D RIGHT DOUBLE QUOTATION MARK otherwise." (interactive) (ucs-insert (if (looking-back smart-quotes-left-context) #x201C #x201D))) (define-minor-mode smart-quotes-mode "Toggle Smart Quotes mode in the current buffer. With argument ARG, turn Smart Quotes mode on iff ARG is positive. In Smart Quotes mode, the ' and \" keys insert left quotation marks if point is preceded by text matching the option `smart-quotes-left-context' and right quotation marks otherwise." :lighter (:eval (string ? (decode-char 'ucs #x201C) (decode-char 'ucs #x201D))) :keymap '(("'" . smart-quotes-insert-single) ("\"" . smart-quotes-insert-double))) (provide 'smart-quotes)
looking-back are new in
Emacs 22. In later releases of Emacs 21 I think you can probably get
away with the following:
(defun ucs-insert (c) "Insert the character whose Unicode code point is C." (insert (decode-char 'ucs c))) (defun looking-back (regexp) "Return non-nil if text before point matches regular expression REGEXP." (and (save-excursion (re-search-backward regexp nil t)) (= (match-end 0) (point))))
But if you’re editing text in a wide range of character sets, you probably want to upgrade to Emacs 22 anyway, as there are lots of improvements to international character support.
Update . Reuben Thomas pointed out that
smart-quotes-left-context needs to match the start of a line. I had wrongly assumed that it would, arguing that the start of any line is preceded by either a newline (which matches the whitespace character class,
\s-), or by the beginning of the buffer (which matches
\`). But newline is only in the whitespace character class in modes like text mode:
(with-syntax-table text-mode-syntax-table (char-syntax ?\n)) ==> 32 ; whitespace class
In programming language modes, newline has special properties:
(with-syntax-table python-mode-syntax-table (char-syntax ?\n)) ==> 62 ; comment ender class
I’m not sure why you’d want to use Smart Quotes minor mode when editing a computer program. But if you do, at least it now gets it right.
Update . Smart Quotes Mode is now on GitHub. Please fork it and send pull requests!