Кликабельный текст — это текст, по которому можно кликнуть, либо мышью, либо с помощью команды клавиатуры, чтобы получить определенный результат. Многие основные режимы используют кликабельный текст для реализации текстовых гиперссылок или, вкратце, ссылок.
Самый простой способ вставки и манипулирования ссылками — использовать пакет button. См. Buttons. В этом разделе мы объясним, как вручную настроить кликабельный текст в буфере, используя свойства текста. Для простоты мы будем называть кликабельный текст ссылкой.
Реализация ссылки включает три отдельных шага: (1) указание кликабельности при наведении курсора на ссылку; (2) выполнение действия при нажатии RET или mouse-2 на этой ссылке; и (3) настройка условия follow-link, чтобы ссылка подчинялась mouse-1-click-follows-link.
Чтобы указать кликабельность, добавьте свойство текста mouse-face к тексту ссылки; тогда Emacs подсветит ссылку при наведении курсора. Кроме того, следует определить всплывающую подсказку или сообщение в области эхо, используя свойство текста help-echo. См. Properties with Special Meanings. Например, вот как Dired указывает, что имена файлов кликабельны:
(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")))
Чтобы сделать ссылку кликабельной, привяжите RET и mouse-2 к командам, выполняющим желаемое действие. Каждая команда должна проверять, была ли она вызвана на ссылке, и действовать соответствующим образом. Например, карта команд основного режима Dired привязывает mouse-2 к следующей команде:
(defun dired-mouse-find-file-other-window (event)
"В Dired посетите имя файла или каталога, на который вы кликнули."
(interactive "e")
(let ((window (posn-window (event-end event)))
(pos (posn-point (event-end event)))
file)
(if (not (windowp window))
(error "Файл не выбран"))
(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)))))
Эта команда использует функции posn-window и posn-point для определения места клика и dired-get-file-for-visit для определения файла, который следует посетить.
Вместо привязки команды мыши в карте команд основного режима вы можете привязать ее внутри текста ссылки, используя свойство текста keymap (см. Properties with Special Meanings). Например:
(let ((map (make-sparse-keymap))) (define-key map [mouse-2] 'operate-this-button) (put-text-property link-start link-end 'keymap map))
С этим методом вы можете легко определять разные команды для разных ссылок. Кроме того, глобальное определение RET и mouse-2 остается доступным для остальной части текста в буфере.
Базовая команда Emacs для клика по ссылкам — mouse-2. Однако, для совместимости с другими графическими приложениями, Emacs также распознает клики mouse-1 по ссылкам, при условии, что пользователь кликает по ссылке быстро, не двигая мышь. Это поведение контролируется опцией пользователя mouse-1-click-follows-link. См. Mouse References в The GNU Emacs Manual.
Чтобы настроить ссылку так, чтобы она подчинялась mouse-1-click-follows-link, вы должны либо (1) применить свойство текста или оверлея follow-link к тексту ссылки, либо (2) привязать событие follow-link к карте команд (это может быть карта команд основного режима или локальная карта команд, указанная через свойство текста keymap). Значение свойства follow-link или привязка события follow-link действует как условие для действия ссылки. Это условие сообщает Emacs две вещи: обстоятельства, при которых клик mouse-1 должен считаться произошедшим внутри ссылки, и как вычислить код действия, который определяет, во что преобразовать клик mouse-1. Условие действия ссылки может быть одним из следующих:
mouse-faceЕсли условие — это символ mouse-face, позиция находится внутри ссылки, если в этой позиции есть свойство mouse-face, отличное от nil. Код действия всегда t.
Например, вот как Info-режим обрабатывает mouse-1:
(keymap-set Info-mode-map "<follow-link>" 'mouse-face)
Если условие — это функция, func, то позиция pos находится внутри ссылки, если (func pos) оценивается как не-nil. Значение, возвращаемое func, служит кодом действия.
Например, вот как pcvs позволяет mouse-1 следовать по ссылкам только для имен файлов:
(keymap-set map "<follow-link>"
(lambda (pos)
(eq (get-char-property pos 'face) 'cvs-filename-face)))
Если значение условия — что-либо другое, то позиция находится внутри ссылки, и само условие является кодом действия. Очевидно, что вы должны указывать такой тип условия только при применении его через свойство текста или оверлея к тексту ссылки (чтобы оно не применялось ко всему буферу).
Код действия сообщает mouse-1, как следовать по ссылке:
Если код действия — это строка или вектор, событие mouse-1 преобразуется в первый элемент строки или вектора; то есть, действие клика mouse-1 — это локальная или глобальная привязка этого символа или знака. Таким образом, если код действия — "foo", mouse-1 преобразуется в f. Если это [foo], mouse-1 преобразуется в foo.
Для любого другого не-nil кода действия событие mouse-1 преобразуется в событие mouse-2 в той же позиции.
Чтобы определить mouse-1 для активации кнопки, определенной с помощью define-button-type, предоставьте кнопке свойство follow-link. Значение свойства должно быть условием действия ссылки, как описано выше. См. Buttons. Например, вот как Help-режим обрабатывает mouse-1:
(define-button-type 'help-xref 'follow-link t 'action #'help-button-action)
Чтобы определить mouse-1 для виджета, определенного с помощью define-widget, предоставьте виджету свойство :follow-link. Значение свойства должно быть условием действия ссылки, как описано выше. Например, вот как виджет link указывает, что клик mouse-1 должен преобразовываться в RET:
(define-widget 'link 'item "Встроенная ссылка." :button-prefix 'widget-link-prefix :button-suffix 'widget-link-suffix :follow-link "\C-m" :help-echo "Перейти по ссылке." :format "%[%t%]")
Эта функция возвращает не-nil, если позиция pos в текущем буфере находится на ссылке. pos также может быть местоположением события мыши, возвращенным event-start (см. Accessing Mouse Events).