Emacs Lisp Examples

Xah Lee, 2005-11

This page shows several very simple elisp functions. They illustrate the basic programing in elisp, but also, they are very useful themselves.

To see a function's documentation, use describe-function (Ctrl+h f). A variable's documentation is describe-variable (Ctrl+h v).

If you have do not know the basics of lisp, goto: elisp basics.


This code illustrates how to insert a string, and also position cursor after the insertion.

(defun insert-p-tag ()
  "Insert <p></p> at cursor point."
  (interactive)
  (insert "<p></p>")
  (backward-char 4))

You can use this code to insert your signature, function template, XML template, headers, footers, etc.


This code shows how to place a string at the beginning and end of a region.

(defun wrap-markup ()
  "Insert a markup <b></b> around a region."
  (interactive)
    (goto-char (region-end)) (insert "</b>")
    (goto-char (region-beginning)) (insert "<b>")
)

You can use this code to wrap a html/xml tag on a selected text.


This code shows you how to set a mark (select text) programatically.

(transient-mark-mode 1)

(defun select-word ()
"Select a word under cursor.
“word” here is considered any alphanumeric sequence with “_” or “-”."
 (interactive)
 (let (b1 b2)
   (skip-chars-backward "-_A-Za-z0-9")
   (setq b1 (point))
   (skip-chars-forward "-_A-Za-z0-9")
   (setq b2 (point))
   (set-mark b1)
 )
)

This code illustrates how to do text replacements on a region. Very useful. For example, you can use it to replace HTML character that needs be encoded. For example:

& → &amp;
< → &lt;
> → &gt;
(defun replace-html-chars-region (start end)
  "Replace “<” to “&lt;” and other chars in HTML.
This works on the current region."
  (interactive "r")
  (save-restriction 
    (narrow-to-region start end)
    (goto-char (point-min))
    (while (search-forward "&" nil t) (replace-match "&amp;" nil t))
    (goto-char (point-min))
    (while (search-forward "<" nil t) (replace-match "&lt;" nil t))
    (goto-char (point-min))
    (while (search-forward ">" nil t) (replace-match "&gt;" nil t))
    )
  )

You can modify the code to do replacement on URL's Percent-encoding. For example:

“ ” → “%20”
“~” → “%e7”
“_” → “%5f”

and so on. You can also use it to do Greek Letter replacement when writing math. For example: alpha → α, beta → β, ...etc.

For some detailed lesson on this code, see: Repeated Find Replace.


This code illustrates how to delete a text enclosed by any pairs of delimiters.

For example, if you are editing HTML code, suppose you have text “<p>how howdy, and blab blab blab</p>” and your cursor is somewhere in between the tags. You want to quickly delete all texts inside the p tags. The following function will do. It will also, delete any text between quotes or parenthesis.

(defun delete-enclosed-text ()
  "Delete texts between any pair of delimiters."
  (interactive)
  (save-excursion
    (let (p1 p2)
      (skip-chars-backward "^(<[“") (setq p1 (point))
      (skip-chars-forward "^)>]”") (setq p2 (point))
      (delete-region p1 p2))))

This example shows how to temporarily change a pre-defined variable's value, then call a function whose behave depends on the var.

“fill-paragraph” is a function that hard-wraps the current paragraph. (it inserts line-return char at about every 70 characters) fill-column is a variable used by fill-paragraph to determine when to chop. It has a value of 70 by default.

(defun remove-line-breaks () 
  "Remove line endings in a paragraph."
  (interactive) 
  (let ((fill-column (point-max))) 
    (fill-paragraph nil)))

In this example, simple lisp constructions are shown, including “while”, “and”, “string-match”. This is also a very convenient function, which allows you to switch to the next buffer by pressing Ctrl+, without going thru a bunch of irrelevant buffers that emacs created such as “*scratch*”, “*Messages*”, “*Shell Command Output*”, “*Completions*”, etc. But when you need to go to one of emacs's buffers, you can press Ctrl+Shift+.

(defun next-user-buffer ()
  "Switch to the next user buffer in cyclic order."
  (interactive)
  (next-buffer)
  (let ((i 0))
    (while (and (string-match "^*" (buffer-name)) (< i 100))
      (setq i (1+ i)) (next-buffer) )))

(defun previous-user-buffer ()
  "Switch to the next user buffer in cyclic order."
  (interactive)
  (previous-buffer)
  (let ((i 0))
    (while (and (string-match "^*" (buffer-name)) (< i 100))
      (setq i (1+ i)) (previous-buffer) )))

(global-set-key (kbd "C-<left>") 'previous-user-buffer)
(global-set-key (kbd "C-<right>") 'next-user-buffer)
(global-set-key (kbd "C-S-<left>") 'previous-buffer)
(global-set-key (kbd "C-S-<right>") 'next-buffer)

This example shows the use of thing-at-point and browse-url.

It will look up the word under the cursor in a online dictionary.

(defun word-definition-lookup ()
"Look up the word under cursor in a browser."
 (interactive)
 (browse-url
  (concat "http://www.answers.com/main/ntquery?s="
          (thing-at-point 'symbol)))
)

If you sometimes need to lookup a phrase, such as “lingua franca”, you can modify the code so that it will take a region if there's one. Like this:

(defun word-definition-lookup ()
"Look up the word's definition in a browser.\n
If a region is active (a phrase), lookup that phrase."
 (interactive)
 (let (myword myurl)
   (setq myword
         (if (and transient-mark-mode mark-active)
             (buffer-substring-no-properties (region-beginning) (region-end))
           (thing-at-point 'symbol)))

  (setq myword (replace-regexp-in-string " " "%20" myword))
  (setq myurl (concat "http://www.answers.com/main/ntquery?s=" myword))
  (browse-url myurl)
   ))

This is useful because you can use it to lookup programing language references too, such as Perl, Pretty Home Page, Java, or any other as long as you know the query url format.

For more detail, see: Dictionary and Reference Lookup with Emacs.


This example shows how to define a function that takes a file path and process the file.

(defun to-unix-eol (fpath)
  "Change file's line ending to unix convention."
  (let (mybuffer)
    (setq mybuffer (find-file fpath))

    (set-buffer-file-coding-system 'unix) ; or 'mac or 'dos
;; do this or that

    (save-buffer)
    (kill-buffer mybuffer)
   )
)

For example, if the file “~/jane/readme.txt” is a Windows file, you can change its line ending by executing the following: “(to-unix-eol "~/jane/readme.txt")”.

You can also edit the line “;; do this or that” to make this function do other things, such as deleting or replacing some words in the file.

The following example shows how to apply a file processing function to a list of files.

(mapcar 'to-unix-eol
 (list
"~/jane/myfile1"
"~/jane/myfile2"
"~/jane/myfile3"
; ...
  )
)

The following code is a example of making a file-processing function that applies to all marked files in dired.

(defun dired-2unix-marked-files ()
  "Change to unix line ending for marked (or next arg) files."
  (interactive)
  (mapcar 'to-unix-eol (dired-get-marked-files))
)

This example shows you how to make lines containing the words “ERROR:” or “NOTE:” highlighted, whenever a file ending in “log” is opened.

(defun highlite-it ()
  "Highlight certain lines..."
  (interactive)
  (if (equal "log" (file-name-extension (buffer-file-name)))
      (progn
        (highlight-lines-matching-regexp "ERROR:" 'hi-red-b) 
        (highlight-lines-matching-regexp "NOTE:" 'hi-blue-b))))

;; the following line will make emacs run highlite-it whenever a file is opened.
;; It works by adding the function highlite-it to list 'find-file-hook
;; find-file is the function that open files
;; find-file-hook is a variable containing functions that will run
;; when find-file is run.
(add-hook 'find-file-hook 'highlite-it)

Sometimes, you need to insert a vertical column of sequential integers into a block of text, like this:

do this x times
do this x times
do this x times
...

where the “x” should be 1, 2, 3, ... The following code does it.

(defun insert-counter-column (n)
  "Insert a sequence of integers vertically.
Example:
do this 1 times
do this 2 times
do this 3 times
...

If there are not enough existing lines after the cursor
when this function is called, it aborts at the last line.

See also: `kill-rectangle' and `string-rectangle'."
  (interactive "nEnter the max integer: ")
  (let ((i 1) colpos)
    (setq colpos (- (point) (point-at-bol)))
    (while (<= i n)
      (insert (number-to-string i))
      (next-line) (beginning-of-line) (forward-char colpos)
      (setq i (1+ i))
      )))

This example shows you how to grab the current paragraph the cursor is on, and do some transformation on it.

This example turns a block of text into a HTML table. The command asks user to enter a string pattern as the separator. For example:

a  b  c
1  2  3
this  and  that

with double space as separator, becomes

<table border="1" cellpadding="5" cellspacing="0">
<tr><td>a</td><td>b</td><td>c</td></tr>
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>this</td><td>and</td><td>that</td></tr>
</table>

and is rendered in browser like this:

abc
123
thisandthat
(defun make-html-table-string (textblock delim)
  "Turn a text string into a HTML table.
See make-html-table."
  (let ()
    (setq textblock (replace-regexp-in-string delim "</td><td>" textblock))
    (setq textblock (replace-regexp-in-string "\n" "</td></tr>\n<tr><td>" textblock))
    (setq textblock (substring textblock 0 -8)) ;; delet the beginning “<tr><td>” in last line
    (concat "<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\">\n<tr><td>" textblock "</table>")
    ))

(defun make-html-table (sep)
  "Turn the current paragraph into a HTML table.

The “current paragraph” is defined as having empty lines before and
after the block of text the cursor is on.

For example:

a•b•c
1•2•3
this•and•that

with “•” as separator, becomes

<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\">
<tr><td>a</td><td>b</td><td>c</td></tr>
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>this</td><td>and</td><td>that</td></tr>
</table>"
  (interactive "sEnter string pattern for column separation:")
  (let (bds p1 p2 myStr)
    (setq bds (bounds-of-thing-at-point 'paragraph))
    (setq p1 (+ (car bds) 1))
    (setq p2 (cdr bds))
    (setq myStr (buffer-substring-no-properties p1 p2))
    (delete-region p1 p2)
    (insert (make-html-table-string myStr sep) "\n")
  ))

For a detailed explanation on the code, see Elisp Lesson: Writing make-html-table.


Related essays:

2005-10
© 2005 by Xah Lee.