Question

I'd like the corresponding, closing HTML tag to be automatically inserted whenever I open one.

So if I type

<div>

I should get

<div></div>

Without having to call to sgml-close-tag myself.

How to achieve this?

Was it helpful?

Solution

Rather than calling a hook function after every single key-stroke, it makes sense to only call it after a > was typed. This can be achieved by rebinding the > character in the keymap that sgml-mode uses.

In addition, sgml-close-tag shouldn't get called if the tag is already closed. Therefore, the following code adds a simple regexp check for that:

(defun my-sgml-insert-gt ()
  "Inserts a `>' character and calls 
`my-sgml-close-tag-if-necessary', leaving point where it is."
  (interactive)
  (insert ">")
  (save-excursion (my-sgml-close-tag-if-necessary)))

(defun my-sgml-close-tag-if-necessary ()
  "Calls sgml-close-tag if the tag immediately before point is
an opening tag that is not followed by a matching closing tag."
  (when (looking-back "<\\s-*\\([^</> \t\r\n]+\\)[^</>]*>")
    (let ((tag (match-string 1)))
      (unless (and (not (sgml-unclosed-tag-p tag))
           (looking-at (concat "\\s-*<\\s-*/\\s-*" tag "\\s-*>")))
    (sgml-close-tag)))))

(eval-after-load "sgml-mode"
  '(define-key sgml-mode-map ">" 'my-sgml-insert-gt))

OTHER TIPS

If you like paredit (and if you're an emacs user, chances are you do), you may be interested in tagedit, an emacs package written by Magnar Sveen that provides paredit-like features for editing html.

The library is here: https://github.com/magnars/tagedit, and can be installed through Melpa/Marmalade (package-install tagedit).

If you enable the experimental features (tagedit-add-experimental-features), then it will automatically close tags for you and keep the corresponding closing tag text matching the opening tag text. That's on top of being able to splice, slurp, barf and all the other crazy things that paredit lets you do when working with balanced expressions...I think it's great!

I'm using yasnippet for this purpose. To type shortcuts this answer, like <kbd>C-o</kbd>, I have the following snippet:

# -*- mode: snippet -*-
# name: kbd
# key: kbd
# --
<kbd>$0</kbd>

So I type kbdC-o and it get's expanded to <kbd></kbd> with cursor right in the middle. You can have the same behavior for div.

You may eval this on your sgml-buffer or add ii to your sgml-hook:

(add-hook 'post-self-insert-hook
          (lambda () (and (eq (char-before) ?>) (sgml-close-tag))) nil t)

Whenever you insert a ">", the function sgml-close-tag will be run for you

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top