Next: Links and Mouse-1, Previous: Lazy Properties, Up: Text Properties
Clickable text is text that can be clicked, with either the
the mouse or via keyboard commands, to produce some result. Many
major modes use clickable text to implement features such as
hyper-links. The button package provides an easy way to insert
and manipulate clickable text. See Buttons.
In this section, we will explain how to manually set up clickable text in a buffer using text properties. This involves two things: (1) indicating clickability when the mouse moves over the text, and (2) making RET or a mouse click on that text do something.
Indicating clickability usually involves highlighting the text, and
often involves displaying helpful information about the action, such
as which mouse button to press, or a short summary of the action.
This can be done with the mouse-face and help-echo
text properties. See Special Properties.
Here is an example of how Dired does it:
(condition-case nil
(if (dired-move-to-filename)
(add-text-properties
(point)
(save-excursion
(dired-move-to-end-of-filename)
(point))
'(mouse-face highlight
help-echo "mouse-2: visit this file in other window")))
(error nil))
The first two arguments to add-text-properties specify the
beginning and end of the text.
The usual way to make the mouse do something when you click it
on this text is to define mouse-2 in the major mode's
keymap. The job of checking whether the click was on clickable text
is done by the command definition. Here is how Dired does it:
(defun dired-mouse-find-file-other-window (event)
"In Dired, visit the file or directory name you click on."
(interactive "e")
(let (window pos file)
(save-excursion
(setq window (posn-window (event-end event))
pos (posn-point (event-end event)))
(if (not (windowp window))
(error "No file chosen"))
(set-buffer (window-buffer window))
(goto-char pos)
(setq file (dired-get-file-for-visit)))
(if (file-directory-p file)
(or (and (cdr dired-subdir-alist)
(dired-goto-subdir file))
(progn
(select-window window)
(dired-other-window file)))
(select-window window)
(find-file-other-window (file-name-sans-versions file t)))))
The reason for the save-excursion construct is to avoid
changing the current buffer. In this case,
Dired uses the functions posn-window and posn-point
to determine which buffer the click happened in and where, and
in that buffer, dired-get-file-for-visit to determine which
file to visit.
Instead of defining a mouse command for the major mode, you can define
a key binding for the clickable text itself, using the keymap
text property:
(let ((map (make-sparse-keymap)))
(define-key map [mouse-2] 'operate-this-button)
(put-text-property (point)
(save-excursion
(dired-move-to-end-of-filename)
(point))
'keymap map))
This method makes it possible to define different commands for various clickable pieces of text. Also, the major mode definition (or the global definition) remains available for the rest of the text in the buffer.