X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/ab1dc14b220747e527d507d40905a24ba5c692d9..259a0b6d3bc6ffe0d5d24368e415fa46f439a844:/lisp/skeleton.el diff --git a/lisp/skeleton.el b/lisp/skeleton.el index b6e1d0a58f..1c6128a33a 100644 --- a/lisp/skeleton.el +++ b/lisp/skeleton.el @@ -1,9 +1,9 @@ ;;; skeleton.el --- Lisp language extension for writing statement skeletons -*- coding: utf-8 -*- -;; Copyright (C) 1993-1996, 2001-2012 Free Software Foundation, Inc. +;; Copyright (C) 1993-1996, 2001-2014 Free Software Foundation, Inc. ;; Author: Daniel Pfeiffer -;; 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.") @@ -84,13 +79,11 @@ The variables `v1' and `v2' are still set when calling this.") "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 @@ -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))))))) ;; A more serious example can be found in sh-script.el