5

I want to create a skeleton, triggered by the abbrev keyword 'func' which checks its context and runs one of two possible sub-skeletons.

Here's what I have:

(define-skeleton my-func-skeleton "func skeleton" "" (if (looking-back "\n") ;; A function at left of screen is a top level function. '((setq str (skeleton-read "Function name: ")) "// " str " ." \n "func " str "(" @ ") {" \n _ @ \n -1 "}") ;; Otherwise it is an anonymous function. '("func () {" \n _ \n -1 "}"))) (expand-add-abbrevs go-mode-abbrev-table '(("func" my-func-skeleton))) 

But this just recursively executes the appropriate sub-skeleton until I quit.

How do I make expressions within skeletons return sub-skeletons that work correctly?

1 Answer 1

5

The manual says the following.

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.

(Emphasis is mine, see section Skeleton Language for more.)

Here's what this means:

By default it repeats until you hit RET or C-g:

(define-skeleton skeleton-repeat-until-tired "repeat until tired" "" ; empty top-level interactor ("Enter something here, or press %s: " ; stops on empty input string "You entered '" str "'.\n")) 

To execute a subskeleton once, use ("") as the interactor:

(define-skeleton skeleton-once "executes a subskeletons once" "" ; empty top-level interactor (("") "insert stuff\n")) 

This is just a special case of an interactor used to loop over several strings:

(define-skeleton skeleton-loop-1 "subskeletons as loops" "" ; empty top-level interactor (("a" "b" "c") ; list if strings, execute subskeleton once per element "str is " str "\n")) 

You can compute these strings based on the context, too:

(defun my-strings () (list (format "you were at line %d" (line-number-at-pos)))) (define-skeleton skeleton-loop-2 "subskeletons as loops" "" ; empty top-level interactor `(,(my-strings) ; list if strings, execute subskeleton once per element "str is " str "\n")) 

Here's one way to use this information to fix your skeleton:

(define-skeleton my-func-skeleton "func skeleton" "" (if (looking-back "\n") ;; A function at left of screen is a top level function. `((,(skeleton-read "Function name: ")) "// " str " ." \n "func " str "(" @ ") {" \n _ @ \n -1 "}") ;; Otherwise it is an anonymous function. '(("") "func () {" \n _ \n -1 "}"))) 
1
  • Wonderful explanation. Commented Nov 26, 2014 at 23:36

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.