1

§12 Skeleton Language lists, as an element of a skeleton input list,

skeleton

 Subskeletons are inserted recursively, not once, but as often as the user enters something at the subskeletons interactor. Thus there must be a `str` in the subskeleton. They can also be used non-interactively, when prompt is a lisp-expression that returns successive list-elements. 

As seems to be common in the skeleton documentation, the terminology is obscure and self-contradictory. I've tried various ways to realise the structure described, but none of my attempts have worked. Here is one of them:

(define-skeleton _skel "Test skeleton" nil ('("Seventeen" "Nineteen") "Should be two values, 17 and 19:" str \n)) 

Invoking _skell results in "Should be two values, 17 and 19:" appearing in the buffer, and an error of setq: Wrong type argument: stringp, ("Seventeen" "Nineteen") appearing in the message buffer.

What am I missing to make this use of subskeletons non-interactively, with either static values or a dynamic lisp-expression returning the values?

Thanks!

4
  • emacs.stackexchange.com/tags/elisp/info Commented Dec 4, 2020 at 0:16
  • Reading the documentation what I do understand is that the interactor (set to nil in your example) should be what returns the list elements and not trying to pass a list to str which expects an atom. Commented Dec 5, 2020 at 9:19
  • I've tried that, too. Of course, AFAIUI, subskeletons need an interactor, too. Hence the confusion. Every combo I've tried has resulted in the same error. :-( Commented Dec 6, 2020 at 18:50
  • Even an example here would be a big help. The code in skeleton.el contains a lot of Deep Magic. Commented Dec 11, 2020 at 22:18

1 Answer 1

1

It's a long time since the question was asked but I figured I would answer since it took me hours to figure this out. This section from emacswiki tipped me off.

The first item of a subskeleton has to be either a string (used as a prompt) or an s-expression that returns a string when evaluated. This string can be produced interactively (using skeleton-read) or non interactively. That means your example needs a function that returns a different string for each call. Iterating over a list like this can be done with a helper function that tracks the state of the iteration with a closure.

(defun make-list-iterator (list) (let ((ls (cons 'discard list))) ; provide item to discard on first call (lambda () (setf ls (cdr ls)) (car ls)))) 

You can then make your example work as you expect like so:

(define-skeleton _skel "Test skeleton" nil ;; Save function doing the iteration in a skeleton-local variable '(fset 'v1 (make-list-iterator '("Seventeen" "Nineteen"))) ((v1) "Should be two values, 17 and 19:" str \n)) 

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.