Next: Fields, Previous: Lazy Properties, Up: Text Properties [Contents][Index]
クリック可能テキスト(clickable text)とは何らかの結果を生成するためにマウスやキーボードコマンドを通じてクリックできるテキストです。多くのメジャーモードがテキスト的なハイパーリンク、略してリンク(link)を実装するためにクリック可能テキストを使用しています。
リンクの挿入や操作を行うもっとも簡単な方法はbuttonパッケージの使用です。Buttonsを参照してください。このセクションではテキストプロパティを使用してバッファー内に手作業でクリック可能テキストをセットアップする方法を説明します。簡略にするためにクリック可能テキストをリンクと呼ぶことにします。
リンクの実装には、(1)リンク上にマウスが移動した際にクリック可能であることを示し、(2)そのリンク上のRETかMouse-2で何かを行うようにして、(3)そのリンクがmouse-1-click-follows-linkにしたがうようfollow-linkをセットアップする、という3つのステップが含まれます。
クリック可能なことを示すためには、そのリンクのテキストにmouse-faceプロパティを追加します。するとEmacsはそれ以降マウスがその上に移動した際にリンクをハイライトするでしょう。加えてhelp-echoテキストプロパティを使用してツールチップかエコーエリアメッセージを定義するべきです。Special Propertiesを参照してください。たとえば以下は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)
"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)))))
このコマンドはクリックがどこで発生したかを判断するために関数posn-windowとposn-point、visitするファイルの判断に関数dired-get-file-for-visitを使用します。
マウスコマンドをメジャーモードキーマップ内でバインドするかわりに、keymapプロパティ(Special Propertiesを参照)を使用してリンクテキスト内でバインドできます。たとえば:
(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 in The GNU Emacs Manualを参照してください。
mouse-1-click-follows-linkにしたがうようにリンクをセットアップするには、(1)そのテキストにfollow-linkテキストプロパティまたはオーバーレイプロパティを適用する、または(2)follow-linkイベントをキーマップ(keymapテキストプロパティを通じたメジャーモードキーマップまたはローカルキーマップ)にバインドするかの、いずれかを行わなければなりません。follow-linkプロパティの値、またはfollow-linkイベントにたいするバインディングはリンクアクションにたいする“コンディション(condition)”として機能します。この条件は、Emacsにたいして2つのことを告げます。それはMouse-1のクリックがそのリンクの“内側”で発生したとみなすべき状況、そしてMouse-1のクリックを何に変換するかを告げる“アクションコード(action
code)”を計算する方法です。そのリンクのアクション条件は、以下のうちの1つです:
mouse-faceコンディションがシンボルmouse-faceの場合には、その位置に非nilのmouse-faceプロパティがあればそれはリンク内側の位置。アクションコードは常にt。
以下はInfoモードがMouse-1を処理する例である:
(define-key Info-mode-map [follow-link] 'mouse-face)
コンディションが関数funcの場合には、(func
pos)が非nilに評価されれば、位置posはリンクの内側。funcがリターンする値はアクションコードとして機能する。
以下はpcvsがファイル名の上でのみMouse-1によるリンクのフォローを有効にする方法の例である:
(define-key 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イベントに変換される。
define-button-typeで定義されるボタンをアクティブにするようにMouse-1を定義するには、そのボタンにfollow-linkプロパティを与えます。このプロパティの値は、上述したリンクのアクションコンディションであること。Buttonsを参照のこと。たとえば以下はHelpモードがMouse-1を処理する例である。
(define-button-type 'help-xref 'follow-link t 'action #'help-button-action)
define-widgetで定義されたウィジェットにMouse-1を定義するには、そのウィジェットに:follow-linkプロパティを与えます。このプロパティの値は、上述したようなリンクのアクションコンディションであるべきです。たとえば、以下はMouse-1クリックがRETに変換されるように、linkウィジェットを指定する方法の例をです:
(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%]")
この関数はカレントバッファー内の位置posがリンク上なら非nilをリターンする。posはevent-startがリターンするようなマウスイベント位置でもよい(Accessing Mouseを参照)。