- str))
-
-
-(defun skeleton-internal-list (definition &optional str recursive start line)
- (condition-case quit
- (progn
- (setq start (save-excursion (beginning-of-line) (point))
- column (current-column)
- line (buffer-substring start
- (save-excursion (end-of-line) (point)))
- str (list 'setq 'str
- (if recursive
- (list 'skeleton-internal-read (list 'quote str))
- (list (if (stringp str)
- 'read-string
- 'eval)
- str))))
- (while (setq modified (eq opoint (point))
- opoint (point)
- definition (cdr definition))
- (skeleton-internal-1 (car definition)))
- ;; maybe continue loop
- recursive)
- (quit ;; remove the subskeleton as far as it has been shown
- (if (eq (cdr quit) 'recursive)
- ()
- ;; the subskeleton shouldn't have deleted outside current line
- (end-of-line)
- (delete-region start (point))
- (insert line)
- (move-to-column column))
- (if (eq (cdr quit) t)
- ;; empty string entered
- nil
- (while (if definition
- (not (eq (car (setq definition (cdr definition)))
- 'resume:))))
- (if definition
- (skeleton-internal-list definition)
- ;; propagate signal we can't handle
- (if recursive (signal 'quit 'recursive)))))))
-
-
-
-(defun skeleton-internal-1 (element)
- (cond ((and (integerp element)
- (< element 0))
- (delete-char element))
- ((char-or-string-p element)
- (insert (if skeleton-transformation
- (funcall skeleton-transformation element)
- element)) )
- ((eq element '\n) ; actually (eq '\n 'n)
- (newline)
- (indent-relative t) )
- ((eq element '>)
- (indent-for-tab-command) )
- ((eq element '<)
- (backward-delete-char-untabify (min tab-width (current-column))) )
- ((eq element '_)
- (or point
- (setq point (point))) )
- ((eq element '&)
- (if modified
- (setq definition (cdr definition))) )
- ((eq element '|)
- (or modified
- (setq definition (cdr definition))) )
- ((if (consp element)
- (or (stringp (car element))
- (consp (car element))))
- (while (skeleton-internal-list element (car element) t)) )
- ((null element) )
- ((skeleton-internal-1 (eval element)) )))
-
+ prompt))
+
+(defun skeleton-internal-list (skeleton &optional str recursive)
+ (let* ((start (save-excursion (beginning-of-line) (point)))
+ (column (current-column))
+ (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) (not recursive)
+ (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))
+ (condition-case quit
+ (skeleton-internal-1 (car skeleton) nil recursive)
+ (quit
+ (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.
+ (end-of-line)
+ (delete-region start (point))
+ (insert line)
+ (move-to-column column)
+ (if (cdr quit)
+ (setq skeleton ()
+ recursive nil)
+ (signal 'quit 'recursive)))))))
+ ;; maybe continue loop or go on to next outer resume: section
+ (if (eq recursive 'quit)
+ (signal 'quit 'recursive)
+ recursive))
+
+(defun skeleton-internal-1 (element &optional literal recursive)
+ (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 (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)) (not recursive) (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 '-)
+ (setq skeleton-point (point)))
+ ((eq element '&)
+ (when skeleton-modified (pop skeleton)))
+ ((eq element '|)
+ (unless skeleton-modified (pop skeleton)))
+ ((eq element '@)
+ (push (point) skeleton-positions))
+ ((eq 'quote (car-safe element))
+ (eval (nth 1 element)))
+ ((and (consp element)
+ (or (stringp (car element)) (listp (car element))))
+ ;; Don't forget: `symbolp' is also true for nil.
+ (if (symbolp (car-safe (car element)))
+ (while (and (skeleton-internal-list element nil t)
+ ;; If the interactor is nil, don't infinite loop.
+ (car element)))
+ (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 recursive))))
+\f
+;; Maybe belongs into simple.el or elsewhere
+;; ;;;###autoload
+;; (define-skeleton local-variables-section
+;; "Insert a local variables section. Use current comment syntax if any."
+;; (completing-read "Mode: " obarray
+;; (lambda (symbol)
+;; (if (commandp symbol)
+;; (string-match "-mode$" (symbol-name symbol))))
+;; t)
+;; '(save-excursion
+;; (if (re-search-forward page-delimiter nil t)
+;; (error "Not on last page")))
+;; comment-start "Local Variables:" comment-end \n
+;; comment-start "mode: " str
+;; & -5 | '(kill-line 0) & -1 | comment-end \n
+;; ( (completing-read (format "Variable, %s: " skeleton-subprompt)
+;; obarray
+;; (lambda (symbol)
+;; (or (eq symbol 'eval)
+;; (user-variable-p symbol)))
+;; t)
+;; comment-start str ": "
+;; (read-from-minibuffer "Expression: " nil read-expression-map nil
+;; 'read-expression-history) | _
+;; comment-end \n)
+;; resume:
+;; comment-start "End:" comment-end \n)