diff options
| author | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
| commit | 754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch) | |
| tree | f1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/elisp/clickable-text.html | |
new repository
Diffstat (limited to 'devdocs/elisp/clickable-text.html')
| -rw-r--r-- | devdocs/elisp/clickable-text.html | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/devdocs/elisp/clickable-text.html b/devdocs/elisp/clickable-text.html new file mode 100644 index 00000000..f4a90bbf --- /dev/null +++ b/devdocs/elisp/clickable-text.html @@ -0,0 +1,62 @@ + <h4 class="subsection">Defining Clickable Text</h4> <p><em>Clickable text</em> is text that can be clicked, with either the mouse or via a keyboard command, to produce some result. Many major modes use clickable text to implement textual hyper-links, or <em>links</em> for short. </p> <p>The easiest way to insert and manipulate links is to use the <code>button</code> package. See <a href="buttons">Buttons</a>. In this section, we will explain how to manually set up clickable text in a buffer, using text properties. For simplicity, we will refer to the clickable text as a <em>link</em>. </p> <p>Implementing a link involves three separate steps: (1) indicating clickability when the mouse moves over the link; (2) making <tt class="key">RET</tt> or <kbd>mouse-2</kbd> on that link do something; and (3) setting up a <code>follow-link</code> condition so that the link obeys <code>mouse-1-click-follows-link</code>. </p> <p>To indicate clickability, add the <code>mouse-face</code> text property to the text of the link; then Emacs will highlight the link when the mouse moves over it. In addition, you should define a tooltip or echo area message, using the <code>help-echo</code> text property. See <a href="special-properties">Special Properties</a>. For instance, here is how Dired indicates that file names are clickable: </p> <div class="example"> <pre class="example"> (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"))) +</pre> +</div> <p>To make the link clickable, bind <tt class="key">RET</tt> and <kbd>mouse-2</kbd> to commands that perform the desired action. Each command should check to see whether it was called on a link, and act accordingly. For instance, Dired’s major mode keymap binds <kbd>mouse-2</kbd> to the following command: </p> <div class="example"> <pre class="example">(defun dired-mouse-find-file-other-window (event) + "In Dired, visit the file or directory name you click on." + (interactive "e") + (let ((window (posn-window (event-end event))) + (pos (posn-point (event-end event))) + file) + (if (not (windowp window)) + (error "No file chosen")) + (with-current-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))))) +</pre> +</div> <p>This command uses the functions <code>posn-window</code> and <code>posn-point</code> to determine where the click occurred, and <code>dired-get-file-for-visit</code> to determine which file to visit. </p> <p>Instead of binding the mouse command in a major mode keymap, you can bind it within the link text, using the <code>keymap</code> text property (see <a href="special-properties">Special Properties</a>). For instance: </p> <div class="example"> <pre class="example">(let ((map (make-sparse-keymap))) + (define-key map [mouse-2] 'operate-this-button) + (put-text-property link-start link-end 'keymap map)) +</pre> +</div> <p>With this method, you can easily define different commands for different links. Furthermore, the global definition of <tt class="key">RET</tt> and <kbd>mouse-2</kbd> remain available for the rest of the text in the buffer. </p> <p>The basic Emacs command for clicking on links is <kbd>mouse-2</kbd>. However, for compatibility with other graphical applications, Emacs also recognizes <kbd>mouse-1</kbd> clicks on links, provided the user clicks on the link quickly without moving the mouse. This behavior is controlled by the user option <code>mouse-1-click-follows-link</code>. See <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Mouse-References.html#Mouse-References">Mouse References</a> in <cite>The GNU Emacs Manual</cite>. </p> <p>To set up the link so that it obeys <code>mouse-1-click-follows-link</code>, you must either (1) apply a <code>follow-link</code> text or overlay property to the link text, or (2) bind the <code>follow-link</code> event to a keymap (which can be a major mode keymap or a local keymap specified via the <code>keymap</code> text property). The value of the <code>follow-link</code> property, or the binding for the <code>follow-link</code> event, acts as a condition for the link action. This condition tells Emacs two things: the circumstances under which a <kbd>mouse-1</kbd> click should be regarded as occurring inside the link, and how to compute an action code that says what to translate the <kbd>mouse-1</kbd> click into. The link action condition can be one of the following: </p> <dl compact> <dt><code>mouse-face</code></dt> <dd> +<p>If the condition is the symbol <code>mouse-face</code>, a position is inside a link if there is a non-<code>nil</code> <code>mouse-face</code> property at that position. The action code is always <code>t</code>. </p> <p>For example, here is how Info mode handles <tt class="key">mouse-1</tt>: </p> <div class="example"> <pre class="example">(define-key Info-mode-map [follow-link] 'mouse-face) +</pre> +</div> </dd> <dt>a function</dt> <dd> +<p>If the condition is a function, <var>func</var>, then a position <var>pos</var> is inside a link if <code>(<var>func</var> <var>pos</var>)</code> evaluates to non-<code>nil</code>. The value returned by <var>func</var> serves as the action code. </p> <p>For example, here is how pcvs enables <kbd>mouse-1</kbd> to follow links on file names only: </p> <div class="example"> <pre class="example">(define-key map [follow-link] + (lambda (pos) + (eq (get-char-property pos 'face) 'cvs-filename-face))) +</pre> +</div> </dd> <dt>anything else</dt> <dd><p>If the condition value is anything else, then the position is inside a link and the condition itself is the action code. Clearly, you should specify this kind of condition only when applying the condition via a text or overlay property on the link text (so that it does not apply to the entire buffer). </p></dd> </dl> <p>The action code tells <kbd>mouse-1</kbd> how to follow the link: </p> <dl compact> <dt>a string or vector</dt> <dd> +<p>If the action code is a string or vector, the <kbd>mouse-1</kbd> event is translated into the first element of the string or vector; i.e., the action of the <kbd>mouse-1</kbd> click is the local or global binding of that character or symbol. Thus, if the action code is <code>"foo"</code>, <kbd>mouse-1</kbd> translates into <kbd>f</kbd>. If it is <code>[foo]</code>, <kbd>mouse-1</kbd> translates into <tt class="key">foo</tt>. </p> </dd> <dt>anything else</dt> <dd><p>For any other non-<code>nil</code> action code, the <kbd>mouse-1</kbd> event is translated into a <kbd>mouse-2</kbd> event at the same position. </p></dd> </dl> <p>To define <kbd>mouse-1</kbd> to activate a button defined with <code>define-button-type</code>, give the button a <code>follow-link</code> property. The property value should be a link action condition, as described above. See <a href="buttons">Buttons</a>. For example, here is how Help mode handles <kbd>mouse-1</kbd>: </p> <div class="example"> <pre class="example">(define-button-type 'help-xref + 'follow-link t + 'action #'help-button-action) +</pre> +</div> <p>To define <kbd>mouse-1</kbd> on a widget defined with <code>define-widget</code>, give the widget a <code>:follow-link</code> property. The property value should be a link action condition, as described above. For example, here is how the <code>link</code> widget specifies that a <tt class="key">mouse-1</tt> click shall be translated to <tt class="key">RET</tt>: </p> <div class="example"> <pre class="example">(define-widget 'link 'item + "An embedded link." + :button-prefix 'widget-link-prefix + :button-suffix 'widget-link-suffix + :follow-link "\C-m" + :help-echo "Follow the link." + :format "%[%t%]") +</pre> +</div> <dl> <dt id="mouse-on-link-p">Function: <strong>mouse-on-link-p</strong> <em>pos</em> +</dt> <dd><p>This function returns non-<code>nil</code> if position <var>pos</var> in the current buffer is on a link. <var>pos</var> can also be a mouse event location, as returned by <code>event-start</code> (see <a href="accessing-mouse">Accessing Mouse</a>). </p></dd> +</dl><div class="_attribution"> + <p class="_attribution-p"> + Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br> + <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Clickable-Text.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Clickable-Text.html</a> + </p> +</div> |
