update nadvice
[bpt/emacs.git] / lisp / skeleton.el
index 328f795..1c6128a 100644 (file)
@@ -1,9 +1,9 @@
 ;;; skeleton.el --- Lisp language extension for writing statement skeletons -*- coding: utf-8 -*-
 
-;; Copyright (C) 1993-1996, 2001-201 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1996, 2001-2014 Free Software Foundation, Inc.
 
 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
-;; Maintainer: FSF
+;; Maintainer: emacs-devel@gnu.org
 ;; Keywords: extensions, abbrev, languages, tools
 
 ;; This file is part of GNU Emacs.
@@ -31,6 +31,8 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'cl-lib))
+
 ;; page 1:     statement skeleton language definition & interpreter
 ;; page 2:     paired insertion
 ;; page 3:     mirror-mode, an example for setting up paired insertion
@@ -53,22 +55,15 @@ Typical examples might be `upcase' or `capitalize'.")
 When the region is visible (due to `transient-mark-mode' or marking a region
 with the mouse) and this is non-nil and the function was called without an
 explicit ARG, then the ARG defaults to -1, i.e. wrapping around the visible
-region.
-
-We will probably delete this variable in a future Emacs version
-unless we get a substantial number of complaints about the auto-wrap
-feature.")
+region.")
+(make-obsolete-variable 'skeleton-autowrap nil "24.5")
 
 (defvar skeleton-end-newline t
   "If non-nil, make sure that the skeleton inserted ends with a newline.
 This just influences the way the default `skeleton-end-hook' behaves.")
 
-(defvar skeleton-end-hook
-  (lambda ()
-    (or (eolp) (not skeleton-end-newline) (newline-and-indent)))
+(defvar skeleton-end-hook nil
   "Hook called at end of skeleton but before going to point of interest.
-By default this moves out anything following to next line,
-  unless `skeleton-end-newline' is set to nil.
 The variables `v1' and `v2' are still set when calling this.")
 
 
@@ -77,20 +72,18 @@ The variables `v1' and `v2' are still set when calling this.")
   "Function for transforming a skeleton proxy's aliases' variable value.")
 (defvaralias 'skeleton-filter 'skeleton-filter-function)
 
-(defvar skeleton-untabify t
+(defvar skeleton-untabify nil          ; bug#12223
   "When non-nil untabifies when deleting backwards with element -ARG.")
 
 (defvar skeleton-newline-indent-rigidly nil
   "When non-nil, indent rigidly under current line for element `\\n'.
 Else use mode's `indent-line-function'.")
 
-(defvar skeleton-further-elements ()
+(defvar-local skeleton-further-elements ()
   "A buffer-local varlist (see `let') of mode specific skeleton elements.
 These variables are bound while interpreting a skeleton.  Their value may
 in turn be any valid skeleton element if they are themselves to be used as
 skeleton elements.")
-(make-variable-buffer-local 'skeleton-further-elements)
-
 
 (defvar skeleton-subprompt
   (substitute-command-keys
@@ -121,7 +114,7 @@ are integer buffer positions in the reverse order of the insertion order.")
   "Define a user-configurable COMMAND that enters a statement skeleton.
 DOCUMENTATION is that of the command.
 SKELETON is as defined under `skeleton-insert'."
-  (declare (debug (&define name stringp skeleton-edebug-spec)))
+  (declare (doc-string 2) (debug (&define name stringp skeleton-edebug-spec)))
   (if skeleton-debug
       (set command skeleton))
   `(progn
@@ -183,7 +176,7 @@ of `str' whereas the skeleton's interactor is then ignored."
 With optional second argument REGIONS, wrap first interesting point
 \(`_') in skeleton around next REGIONS words, if REGIONS is positive.
 If REGIONS is negative, wrap REGIONS preceding interregions into first
-REGIONS interesting positions \(successive `_'s) in skeleton.
+REGIONS interesting positions (successive `_'s) in skeleton.
 
 An interregion is the stretch of text between two contiguous marked
 points.  If you marked A B C [] (where [] is the cursor) in
@@ -200,7 +193,9 @@ not needed, a prompt-string or an expression for complex read functions.
 If ELEMENT is a string or a character it gets inserted (see also
 `skeleton-transformation-function').  Other possibilities are:
 
-       \\n     go to next line and indent according to mode
+       \\n     go to next line and indent according to mode, unless
+                this is the first/last element of a skeleton and point
+                is at bol/eol
        _       interesting point, interregion here
        -       interesting point, no interregion interaction, overrides
                interesting point set by _
@@ -208,21 +203,26 @@ If ELEMENT is a string or a character it gets inserted (see also
        @       add position to `skeleton-positions'
        &       do next ELEMENT if previous moved point
        |       do next ELEMENT if previous didn't move point
-       -num    delete num preceding characters (see `skeleton-untabify')
+       -NUM    delete NUM preceding characters (see `skeleton-untabify')
        resume: skipped, continue here if quit is signaled
        nil     skipped
 
 After termination, point will be positioned at the last occurrence of -
 or at the first occurrence of _ or at the end of the inserted text.
 
-Further elements can be defined via `skeleton-further-elements'.  ELEMENT may
-itself be a SKELETON with an INTERACTOR.  The user is prompted repeatedly for
-different inputs.  The SKELETON is processed as often as the user enters a
-non-empty string.  \\[keyboard-quit] terminates skeleton insertion, but
-continues after `resume:' and positions at `_' if any.  If INTERACTOR in such
-a subskeleton is a prompt-string which contains a \".. %s ..\" it is
-formatted with `skeleton-subprompt'.  Such an INTERACTOR may also be a list of
-strings with the subskeleton being repeated once for each string.
+Note that \\n as the last element of the skeleton only inserts a
+newline if not at eol.  If you want to unconditionally insert a newline
+at the end of the skeleton, use \"\\n\" instead.  Likewise with \\n
+as the first element when at bol.
+
+Further elements can be defined via `skeleton-further-elements'.
+ELEMENT may itself be a SKELETON with an INTERACTOR.  The user is prompted
+repeatedly for different inputs.  The SKELETON is processed as often as
+the user enters a non-empty string.  \\[keyboard-quit] terminates skeleton insertion, but
+continues after `resume:' and positions at `_' if any.  If INTERACTOR in
+such a subskeleton is a prompt-string which contains a \".. %s ..\" it is
+formatted with `skeleton-subprompt'.  Such an INTERACTOR may also be a list
+of strings with the subskeleton being repeated once for each string.
 
 Quoted Lisp expressions are evaluated for their side-effects.
 Other Lisp expressions are evaluated and the value treated as above.
@@ -260,8 +260,11 @@ When done with skeleton, but before going back to `_'-point call
          skeleton-modified skeleton-point resume: help input v1 v2)
       (setq skeleton-positions nil)
       (unwind-protect
-         (eval `(let ,skeleton-further-elements
-                  (skeleton-internal-list skeleton str)))
+         (cl-progv
+              (mapcar #'car skeleton-further-elements)
+              (mapcar (lambda (x) (eval (cadr x))) skeleton-further-elements)
+            (skeleton-internal-list skeleton str))
+       (or (eolp) (not skeleton-end-newline) (newline-and-indent))
        (run-hooks 'skeleton-end-hook)
        (sit-for 0)
        (or (pos-visible-in-window-p beg)
@@ -354,15 +357,6 @@ automatically, and you are prompted to fill in the variable parts.")))
       (signal 'quit 'recursive)
     recursive))
 
-(defun skeleton-newline ()
-  (if (or (eq (point) skeleton-point)
-          (eq (point) (car skeleton-positions)))
-      ;; If point is recorded, avoid `newline' since it may do things like
-      ;; strip trailing spaces, and since recorded points are commonly placed
-      ;; right after a trailing space, calling `newline' can destroy the
-      ;; position and renders the recorded position incorrect.
-      (insert "\n")
-    (newline)))
 
 (defun skeleton-internal-1 (element &optional literal recursive)
   (cond
@@ -382,7 +376,7 @@ automatically, and you are prompted to fill in the variable parts.")))
     (let ((pos (if (eq element '>) (point))))
       (cond
        ((and skeleton-regions (eq (nth 1 skeleton-il) '_))
-       (or (eolp) (newline))
+       (or (eolp) (insert "\n"))
        (if pos (save-excursion (goto-char pos) (indent-according-to-mode)))
        (indent-region (line-beginning-position)
                       (car skeleton-regions) nil))
@@ -391,13 +385,13 @@ automatically, and you are prompted to fill in the variable parts.")))
        (if pos (indent-according-to-mode)))
        (skeleton-newline-indent-rigidly
        (let ((pt (point)))
-         (skeleton-newline)
+          (insert "\n")
          (indent-to (save-excursion
                       (goto-char pt)
                       (if pos (indent-according-to-mode))
                       (current-indentation)))))
        (t (if pos (reindent-then-newline-and-indent)
-           (skeleton-newline)
+           (insert "\n")
            (indent-according-to-mode))))))
    ((eq element '>)
     (if (and skeleton-regions (eq (nth 1 skeleton-il) '_))
@@ -516,7 +510,6 @@ symmetrical ones, and the same character twice for the others."
     (let* ((mark (and skeleton-autowrap
                      (or (eq last-command 'mouse-drag-region)
                          (and transient-mark-mode mark-active))))
-          (skeleton-end-hook)
           (char last-command-event)
           (skeleton (or (assq char skeleton-pair-alist)
                         (assq char skeleton-pair-default-alist)
@@ -527,7 +520,9 @@ symmetrical ones, and the same character twice for the others."
                       (if (not skeleton-pair-on-word) (looking-at "\\w"))
                       (funcall skeleton-pair-filter-function))))
          (self-insert-command (prefix-numeric-value arg))
-       (skeleton-insert (cons nil skeleton) (if mark -1))))))
+       ;; Newlines not desirable for inserting pairs.  See bug#16138.
+       (let ((skeleton-end-newline nil))
+         (skeleton-insert (cons nil skeleton) (if mark -1)))))))
 
 \f
 ;; A more serious example can be found in sh-script.el