;; Copyright (C) 1993, 1994, 1995, 1996 by Free Software Foundation, Inc.
-;; Author: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
+;; Author: Daniel Pfeiffer <occitan@esperanto.org>
;; Maintainer: FSF
;; Keywords: extensions, abbrev, languages, tools
;; page 3: mirror-mode, an example for setting up paired insertion
-(defvar skeleton-transformation nil
+(defvar skeleton-transformation 'identity
"*If non-nil, function applied to literal strings before they are inserted.
It should take strings and characters and return them transformed, or nil
which means no transformation.
unless we get a substantial number of complaints about the auto-wrap
feature.")
+(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) (newline-and-indent)))
+ (or (eolp) (not skeleton-end-newline) (newline-and-indent)))
"Hook called at end of skeleton but before going to point of interest.
-By default this moves out anything following to next line.
+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.")
around the region text.
A prefix argument ARG says to wrap the skeleton around the next ARG words.
+A prefix argument of -1 says to wrap around region, even if not highlighted.
A prefix argument of zero says to wrap around zero words---that is, nothing.
-This is a way of overiding the use of a highlighted region.")
+This is a way of overriding the use of a highlighted region.")
(interactive "*P\nP")
(skeleton-proxy-new ',skeleton str arg))))
`skeleton-transformation'). Other possibilities are:
\\n go to next line and indent according to mode
- _ interesting point, interregion here, point after termination
+ _ interesting point, interregion here
> indent line (or interregion if > _) according to major mode
@ add position to `skeleton-positions'
- & do next ELEMENT if previous moved point
- | do next ELEMENT if previous didn't move point
+ & do next ELEMENT iff previous moved point
+ | do next ELEMENT iff previous didn't move point
-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 first occurrence
+of _ or @ 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
(and skeleton-regions
(setq skeleton-regions
(if (> skeleton-regions 0)
- (list (point-marker)
+ (list (copy-marker (point) t)
(save-excursion (forward-word skeleton-regions)
(point-marker)))
(setq skeleton-regions (- skeleton-regions))
;; copy skeleton-regions - 1 elements from `mark-ring'
(let ((l1 (cons (mark-marker) mark-ring))
- (l2 (list (point-marker))))
+ (l2 (list (copy-marker (point) t))))
(while (and l1 (> skeleton-regions 0))
- (setq l2 (cons (car l1) l2)
- skeleton-regions (1- skeleton-regions)
- l1 (cdr l1)))
+ (push (copy-marker (pop l1) t) l2)
+ (setq skeleton-regions (1- skeleton-regions)))
(sort l2 '<))))
(goto-char (car skeleton-regions))
(setq skeleton-regions (cdr skeleton-regions)))
(defun skeleton-read (prompt &optional initial-input recursive)
"Function for reading a string from the minibuffer within skeletons.
-PROMPT may contain a `%s' which will be replaced by `skeleton-subprompt'.
+
+PROMPT must be a string or a form that evaluates to a string.
+It may contain a `%s' which will be replaced by `skeleton-subprompt'.
If non-`nil' second arg INITIAL-INPUT or variable `input' is a string or
cons with index to insert before reading. If third arg RECURSIVE is non-`nil'
i.e. we are handling the iterator of a subskeleton, returns empty string if
(defun skeleton-internal-list (skeleton &optional str recursive)
(let* ((start (save-excursion (beginning-of-line) (point)))
(column (current-column))
- (line (buffer-substring start
- (save-excursion (end-of-line) (point))))
+ (line (buffer-substring start (line-end-position)))
opoint)
(or str
(setq str `(setq str (skeleton-read ',(car skeleton) nil ,recursive))))
+ (when (and (eq (cadr skeleton) '\n)
+ (save-excursion (skip-chars-backward " \t") (bolp)))
+ (setq skeleton (cons nil (cons '> (cddr skeleton)))))
(while (setq skeleton-modified (eq opoint (point))
opoint (point)
skeleton (cdr skeleton))
(if (eq (cdr quit) 'recursive)
(setq recursive 'quit
skeleton (memq 'resume: skeleton))
- ;; remove the subskeleton as far as it has been shown
- ;; the subskeleton shouldn't have deleted outside current line
+ ;; Remove the subskeleton as far as it has been shown
+ ;; the subskeleton shouldn't have deleted outside current line.
(end-of-line)
(delete-region start (point))
(insert line)
(signal 'quit 'recursive)
recursive))
-
(defun skeleton-internal-1 (element &optional literal)
- (cond ((char-or-string-p element)
- (if (and (integerp element) ; -num
- (< element 0))
- (if skeleton-untabify
- (backward-delete-char-untabify (- element))
- (delete-backward-char (- element)))
- (insert-before-markers (if (and skeleton-transformation
- (not literal))
- (funcall skeleton-transformation element)
- element))))
- ((eq element '\n) ; actually (eq '\n 'n)
- (if (and skeleton-regions
- (eq (nth 1 skeleton) '_))
- (progn
- (or (eolp)
- (newline))
- (indent-region (point) (car skeleton-regions) nil))
- (if skeleton-newline-indent-rigidly
- (indent-to (prog1 (current-indentation)
- (newline)))
- (newline)
- (indent-according-to-mode))))
- ((eq element '>)
- (if (and skeleton-regions
- (eq (nth 1 skeleton) '_))
- (indent-region (point) (car skeleton-regions) nil)
- (indent-according-to-mode)))
- ((eq element '_)
- (if skeleton-regions
- (progn
- (goto-char (car skeleton-regions))
- (setq skeleton-regions (cdr skeleton-regions))
- (and (<= (current-column) (current-indentation))
- (eq (nth 1 skeleton) '\n)
- (end-of-line 0)))
- (or skeleton-point
- (setq skeleton-point (point)))))
+ (cond
+ ((char-or-string-p element)
+ (if (and (integerp element) ; -num
+ (< element 0))
+ (if skeleton-untabify
+ (backward-delete-char-untabify (- element))
+ (delete-backward-char (- element)))
+ (insert (if (and skeleton-transformation
+ (not literal))
+ (funcall skeleton-transformation element)
+ element))))
+ ((or (eq element '\n) ; actually (eq '\n 'n)
+ ;; The sequence `> \n' is handled specially so as to indent the first
+ ;; line after inserting the newline (to get the proper indentation).
+ (and (eq element '>) (eq (nth 1 skeleton) '\n) (pop skeleton)))
+ (let ((pos (if (eq element '>) (point))))
+ (cond
+ ((and skeleton-regions (eq (nth 1 skeleton) '_))
+ (or (eolp) (newline))
+ (if pos (save-excursion (goto-char pos) (indent-according-to-mode)))
+ (indent-region (line-beginning-position)
+ (car skeleton-regions) nil))
+ ;; \n as last element only inserts \n if not at eol.
+ ((and (null (cdr skeleton)) (eolp))
+ (if pos (indent-according-to-mode)))
+ (skeleton-newline-indent-rigidly
+ (let ((pt (point)))
+ (newline)
+ (indent-to (save-excursion
+ (goto-char pt)
+ (if pos (indent-according-to-mode))
+ (current-indentation)))))
+ (t (if pos (reindent-then-newline-and-indent)
+ (newline)
+ (indent-according-to-mode))))))
+ ((eq element '>)
+ (if (and skeleton-regions (eq (nth 1 skeleton) '_))
+ (indent-region (line-beginning-position)
+ (car skeleton-regions) nil)
+ (indent-according-to-mode)))
+ ((eq element '_)
+ (if skeleton-regions
+ (progn
+ (goto-char (pop skeleton-regions))
+ (and (<= (current-column) (current-indentation))
+ (eq (nth 1 skeleton) '\n)
+ (end-of-line 0)))
+ (or skeleton-point
+ (setq skeleton-point (point)))))
((eq element '&)
- (if skeleton-modified
- (setq skeleton (cdr skeleton))))
- ((eq element '|)
- (or skeleton-modified
- (setq skeleton (cdr skeleton))))
- ((eq element '@)
- (setq skeleton-positions (cons (point) skeleton-positions)))
- ((eq 'quote (car-safe element))
- (eval (nth 1 element)))
- ((or (stringp (car-safe element))
- (consp (car-safe element)))
- (if (symbolp (car-safe (car element)))
- (while (skeleton-internal-list element nil t))
- (setq literal (car element))
- (while literal
- (skeleton-internal-list element (car literal))
- (setq literal (cdr literal)))))
- ((null element))
- ((skeleton-internal-1 (eval element) t))))
-
-
+ (when skeleton-modified (pop skeleton)))
+ ((eq element '|)
+ (unless skeleton-modified (pop skeleton)))
+ ((eq element '@)
+ (push (point) skeleton-positions)
+ (unless skeleton-point (setq skeleton-point (point))))
+ ((eq 'quote (car-safe element))
+ (eval (nth 1 element)))
+ ((or (stringp (car-safe element))
+ (consp (car-safe element)))
+ (if (symbolp (car-safe (car element)))
+ (while (skeleton-internal-list element nil t))
+ (setq literal (car element))
+ (while literal
+ (skeleton-internal-list element (car literal))
+ (setq literal (cdr literal)))))
+ ((null element))
+ (t (skeleton-internal-1 (eval element) t))))
+\f
;; Maybe belongs into simple.el or elsewhere
-;; ;###autoload
-;;; (define-skeleton local-variables-section
+;; ;;;###autoload
+;; (define-skeleton local-variables-section
;; "Insert a local variables section. Use current comment syntax if any."
;; (completing-read "Mode: " obarray
;; (lambda (symbol)
;; t)
;; '(save-excursion
;; (if (re-search-forward page-delimiter nil t)
-;; (error "Not on last page.")))
+;; (error "Not on last page")))
;; comment-start "Local Variables:" comment-end \n
;; comment-start "mode: " str
;; & -5 | '(kill-line 0) & -1 | comment-end \n
"*If this is nil, paired insertion is inhibited before or inside a word.")
-(defvar skeleton-pair-filter (lambda ())
+(defvar skeleton-pair-filter (lambda () nil)
"Attempt paired insertion if this function returns nil, before inserting.
This allows for context-sensitive checking whether pairing is appropriate.")
is visible the pair is wrapped around it depending on `skeleton-autowrap'.
Else, if `skeleton-pair-on-word' is non-nil or we are not before or inside a
word, and if `skeleton-pair-filter' returns nil, pairing is performed.
+Pairing is also prohibited if we are right after a quoting character
+such as backslash.
If a match is found in `skeleton-pair-alist', that is inserted, else
the defaults are used. These are (), [], {}, <> and `' for the
(skeleton-end-hook))
(if (or arg
(not skeleton-pair)
+ (memq (char-syntax (preceding-char)) '(?\\ ?/))
(and (not mark)
(or overwrite-mode
(if (not skeleton-pair-on-word) (looking-at "\\w"))
(provide 'skeleton)
-;; skeleton.el ends here
+;;; skeleton.el ends here