tags:

views:

505

answers:

3

In TextMate, one can use ctrl-shift-w to wrap text in an Open/Close tag and ctrl-shift-cmd-w to wrap each line in a region in Open/Close tags. How can I implement this same functionality in Emacs using emacs lisp?

emacs

becomes

<p>emacs</p>

And ...

emacs
textmate
vi

becomes

<li>emacs</li>
<li>textmate</li>
<li>vi</li>
+4  A: 

This answer gives you a solution for wrapping the region (once you modify it to use angle brackets).

This routine will prompt you for the tag to use, and should tag every line in the region with an open/close tag of that type:

(defun my-tag-lines (b e tag)
  "'tag' every line in the region with a tag"
  (interactive "r\nMTag for line: ")
  (save-restriction
    (narrow-to-region b e)
    (save-excursion
      (goto-char (point-min))
      (while (< (point) (point-max))
        (beginning-of-line)
        (insert (format "<%s>" tag))
        (end-of-line)
        (insert (format "</%s>" tag))
        (forward-line 1)))))

*Note: *If you wanted the tag to always be li, then remove the tag argument, remove the text \nMTag for line: from the call to interactive, and update the insert calls to just insert the "<li\>" as you would expect.

Trey Jackson
+1  A: 

yasnippet is a particularly good implementation of Textmate's snippet syntax for Emacs. With that you can import all of Textmate's snippets. If you install it then, this snippet that I wrote should do what you want:

(defun wrap-region-or-point-with-html-tag (start end)
  "Wraps the selected text or the point with a tag"
  (interactive "r")
  (let (string)
    (if mark-active 
        (list (setq string (buffer-substring start end))
          (delete-region start end)))
    (yas/expand-snippet (point)
                        (point)
                        (concat "<${1:p}>" string "$0</${1:$(replace-regexp-in-string \" .*\" \"\" text)}>"))))

(global-set-key (kbd "C-W") 'wrap-region-or-point-with-html-tag)

EDIT: (Okay this is my last attempt at fixing this. It is exactly like Textmate's version. It even ignores characters after a space in the end tag)

Sorry I misread your question. This function should edit each line in the region.

(defun wrap-lines-in-region-with-html-tag (start end)
  "Wraps the selected text or the point with a tag"
  (interactive "r")
  (let (string)
    (if mark-active 
        (list (setq string (buffer-substring start end))
              (delete-region start end)))
    (yas/expand-snippet
     (replace-regexp-in-string "\\(<$1>\\).*\\'" "<${1:p}>"
      (mapconcat
       (lambda (line) (format "%s" line))
       (mapcar
        (lambda (match) (concat "<$1>" match "</${1:$(replace-regexp-in-string \" .*\" \"\" text)}>"))
        (split-string string "[\r\n]")) "\n") t nil 1) (point) (point))))
Singletoned
+1  A: 

For sgml-mode deratives, mark region to tagify, type M-x sgml-tag, and type the tag name you like to use (press TAB to get list of available HTML elements). Altough, this method does not allow you to tagify each line in a region, you can work around this by recording a keyboard macro.

Török Gábor