Emacs: Wrap lines in html tags
Before I switched to Emacs, I used TextMate and was mightily impresed by it. (I still am). There are lots of little touches in there that haven’t been done better in any other editor, and the snippet syntax is one of the best balances between ease of use and power I’ve seen for a long time.
However Emacs is better, cause Steve Yegge says so, and so I switched. I used yasnippet for while, and loved it. It’s a reworking of TextMate’s snippet system with added Lisp; more power without a sacrifice in ease of use. For some reason I stopped using, but since a StackOverflow question recently inspired me, I’m back with a vengence.
A yasnippet to wrap a region or the point in a html tag:
(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)
I wrote this a while, and at the time it was one of the most complicated pieces of Lisp I had written.
I initially misread the StackOverflow question, and submitted the previous function. However once I realised that they wanted something more complex, I felt challenged and dived right in. I eventually came up with this, which hasn’t really been tested:
(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))))
From the end of the function working back (which seems to be the way with Functional style), it:
- splits the region by linebreaks
- wraps each line with the yasnippet syntax
- formats each entry as a string
- concatenates all those strings
- replaces the first yasnippet marker with a yasnippet default marker.
I think I should be able to do something better instead of (lambda (line) (format "%s" line)) but I don’t know what.
Definitely the most complex lisp I’ve written to date and I’ve learned quite a lot from writing it.
As always, improvements and suggestions welcome; help yourself to any code.
