3

auto-insert-alist by default matches files created in .../bin/ directories and enables sh-mode.

There are examples on the wiki showing how to use a skeleton to insert some text, but I want to both insert some text and enable sh-mode. Some other examples show using a vector to run multiple actions, but not with a skeleton.

I'm unsure of the syntax. This doesn't work:

(auto-insert-mode +1)
(setq-default auto-insert-query nil)

(define-auto-insert
  '("/bin/.*[^/]\\'" . "Shell-Script")
  ['("Default shell script: "
    "#!/bin/bash" \n \n
    > _)
   sh-mode])

Can you show the correct way to use vectors and skeletons?

Skeletor
  • 33
  • 4

1 Answers1

5

This works for me:

(define-auto-insert
  '("/bin/.*[^/]\\'" . "Shell-Script")
  [(lambda () (sh-mode))
   ("Default shell script: "
    "#!/bin/bash\n\n"
    > _)])

There are two issues here.

  1. auto-insert can call functions as a part of the action, but for some reason it has to be a lambda form. (I wonder why it checks for lambda instead of calling functionp...)
  2. The [...] format for creating vectors does not evaluate its contents. (See section Vectors of the Emacs Lisp Manual.)

The second issue means that these two expressions have the same value:

(vector (lambda () (sh-mode))
        '("Default shell script: "
          "#!/bin/bash\n\n"
          \> _))

[(lambda () (sh-mode))
   ("Default shell script: "
    "#!/bin/bash\n\n"
    > _)]

Note that in the second expression vector elements are not quoted.

In addition to this, one needs to be careful when using \n at the end of a skeleton, so I added newlines to the string.

The documentation for skeleton-insert states:

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.
Constantine
  • 9,072
  • 1
  • 34
  • 49