[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

30. マーカ

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Markers"
"texi/elisp21/マーカ"へのコメント(無し)

マーカ(marker)とは、バッファ内位置をそれを取り巻くテキストを 基準に指定するために使われるLispオブジェクトです。 テキストが挿入されたり削除されると、 バッファの先頭からマーカまでの距離は自動的に変更され、 マーカは同じ前後の文字のあいだに留まります。



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

30.1 マーカの概要

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Overview%20of%20Markers"
"texi/elisp21/マーカの概要"へのコメント(無し)

マーカは、バッファとそのバッファ内での位置を指定します。 マーカは、位置を必要とする関数に対して位置を表すものとして使えます。 バッファ内の位置について詳しくはSee 節 29. バッファ内の位置

マーカには2つの属性、つまり、マーカ位置とマーカバッファがあります。 マーカ位置は、当該バッファ内の位置としてのマーカに (その時点で)等価な整数です。 しかし、マーカの生存期間中、マーカ位置の値はしばしば変化します。 バッファにテキストを挿入したり削除すると、マーカは再配置されます。 これは、バッファの任意の箇所で挿入したり削除したとしても、 2つの文字のあいだに置かれたマーカが 同じ文字のあいだに留まるようにするためです。 再配置によって、マーカに等価な整数は変わります。

マーカ位置の周りのテキストを削除すると、 削除されたテキストの前後の文字のあいだにマーカは留まります。 マーカの位置にテキストを挿入すると、 insert-before-markers(see 節 31.4 テキストの挿入)で挿入しない限り、 マーカの挿入型(insertion type)(see 節 30.5 マーカの挿入型)に 依存して、マーカは挿入されたテキストのまえかうしろに留まります。

バッファに対する挿入や削除では、 すべてのマーカを検査し、必要ならばマーカを再配置する必要があります。 マーカを多数抱えるバッファでは、このために処理が遅くなります。 そのため、マーカが不要であると確信したときには、 マーカがどこも指さないようにしておくのがよいです。 参照されていないマーカは最終的には(ガベッジコレクションで)回収されますが、 それまでは、マーカがどこかを指していると処理時間を浪費します。

マーカ位置にはよく算術演算を施すので、 (+-を含む)ほとんどの算術演算は 引数としてマーカを受け付けます。 そのような場合、マーカはその現在位置を表します。

マーカを作って位置を設定し、ポイントをマーカへ移動する例を示します。

 
;; どこも指していない新しいマーカを作る
(setq m1 (make-marker))
     => #

;; マーカm1の位置をカレントバッファの
;; 99番目と100番目の文字のあいだにする
(set-marker m1 100)
     => #

;; バッファの先頭に1文字挿入する
(goto-char (point-min))
     => 1
(insert "Q")
     => nil

;; それにしたがってm1が更新される
m1
     => #

;; 同じ位置を指す2つのマーカはeqではないが
;; equalである
(setq m2 (copy-marker m1))
     => #
(eq m1 m2)
     => nil
(equal m1 m2)
     => t

;; マーカを使い終ったら、どこも指していないようにする
(set-marker m1 nil)
     => #



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

30.2 マーカ向けの述語

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Predicates%20on%20Markers"
"texi/elisp21/マーカ向けの述語"へのコメント(無し)

オブジェクトがマーカであるかどうかや、 オブジェクトが整数かマーカであるかどうかを検査できます。 マーカと整数の両者を扱う算術関数に関連して、 後者の検査は有用です。

Function: markerp object
この関数は、objectがマーカであればtを返し、 さもなければnilを返す。 多くの関数がマーカや整数を受け付けるが、 整数はマーカではないことに注意すること。

Function: integer-or-marker-p object
この関数は、objectが整数かマーカであるとtを返し、 さもなければnilを返す。

Function: number-or-marker-p object
この関数は、objectが数(整数か浮動小数点数)かマーカであると tを返し、さもなければnilを返す。



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

30.3 マーカ作成関数

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Creating%20Markers"
"texi/elisp21/マーカ作成関数"へのコメント(無し)

新たにマーカを作成するときには、そのマーカが、 どこも指していない、現在のポイント位置を指している、 バッファの参照可能部分の先頭や末尾を指している、 別のマーカと同じ箇所を指しているのいずれかにできます。

Function: make-marker
この関数は、どこも指していない新たに作成したマーカを返す。

 
(make-marker)
     => #

Function: point-marker
この関数は、カレントバッファの現在のポイント位置を 指す新たに作成したマーカを返す。 see 節 29.1 ポイント。 例については、下記のcopy-markerを参照。

Function: point-min-marker
この関数は、バッファの参照可能部分の先頭を指す新たに作成したマーカを返す。 ナロイングしていなければ、これはバッファの先頭である。 see 節 29.4 ナロイング

Function: point-max-marker
この関数は、バッファの参照可能部分の末尾を指す新たに作成したマーカを返す。 ナロイングしていなければ、これはバッファの末尾である。 see 節 29.4 ナロイング

本章のソースファイル(の原文)を入れたバッファでの この関数とpoint-min-markerの例を示す。

 
(point-min-marker)
     => #
(point-max-marker)
     => #

(narrow-to-region 100 200)
     => nil
(point-min-marker)
     => #
(point-max-marker)
     => #

Function: copy-marker marker-or-integer &optional insertion-type
引数としてマーカを渡されると、copy-markerは、 marker-or-integerが指すのと同じ バッファとバッファ内位置を指す新たなマーカを返す。 引数として整数を渡されると、copy-markerは、 カレントバッファで位置marker-or-integerを指す新たなマーカを返す。

新たなマーカの挿入型は引数insertion-typeで指定する。 see 節 30.5 マーカの挿入型

渡された整数引数が1未満であると、copy-markerは、 カレントバッファでバッファの先頭を指す新たなマーカを返す。 渡された整数引数がバッファの長さより大きいと、copy-markerは、 バッファの末尾を指す新たなマーカを返す。

 
(copy-marker 0)
     => #

(copy-marker 20000)
     => #

marker-or-integerがマーカでも整数でもないと、エラーを通知する。

2つの異なるマーカが、同じバッファの同じバッファ内位置であるか、 どちらもどこも指していないときには、 両者を(eqではないが)equalとみなします。

 
(setq p (point-marker))
     => #

(setq q (copy-marker p))
     => #

(eq p q)
     => nil

(equal p q)
     => t



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

30.4 マーカの情報

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Information%20from%20Markers"
"texi/elisp21/マーカの情報"へのコメント(無し)

本節では、マーカオブジェクトの構成要素を参照する関数について述べます。

Function: marker-position marker
この関数は、markerが指す位置を返す。 あるいは、markerがどこも指していなければnilを返す。

Function: marker-buffer marker
この関数は、markerが指すバッファを返す。 あるいは、markerがどこも指していなければnilを返す。

 
(setq m (make-marker))
     => #
(marker-position m)
     => nil
(marker-buffer m)
     => nil

(set-marker m 3770 (current-buffer))
     => #
(marker-buffer m)
     => #
(marker-position m)
     => 3770



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

30.5 マーカの挿入型

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Marker%20Insertion%20Types"
"texi/elisp21/マーカの挿入型"へのコメント(無し)

マーカが指す箇所に直接テキストを挿入すると、 マーカの再配置方法には2つの可能性、つまり、 挿入したテキストのまえに留まるか、あとにくるかのどちらかです。 マーカの挿入型(insertion type)を設定することで、 あるマーカではどちらを選ぶか指定できます。 insert-before-markersを使うとマーカの挿入型は無視され、 マーカは挿入したテキストのうしろにつねに再配置されることに注意してください。

Function: set-marker-insertion-type marker type
この関数は、マーカmarkerの挿入型をtypeとする。 typetであると、 テキストが挿入されるとmarkerはその位置へ進む。 typenilであると、 テキストが挿入されてもmarkerはその位置へ進まない。

Function: marker-insertion-type marker
この関数は、markerの現在の挿入型を報告する。



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

30.6 マーカ位置の移動

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Moving%20Markers"
"texi/elisp21/マーカ位置の移動"へのコメント(無し)

本節では、既存のマーカの位置を変更する方法について述べます。 これを行うときには、読者のプログラムの外側で 当該マーカが使われているかどうか、 使われているときには移動による効果はなにかを確実に理解してください。 さもないと、Emacsの別の部分で混乱を生じるかもしれません。

Function: set-marker marker position &optional buffer
この関数は、bufferにおいてmarkerpositionへ移動する。 bufferを与えないと、デフォルトはカレントバッファである。

positionが1未満であると、 set-markermarkerをバッファの先頭へ移動する。 positionがバッファのサイズよりも大きいと、 set-markermarkerをバッファの末尾へ移動する。 positionnilであったりどこも指していないマーカであると、 markerはどこも指さないようにする。

戻り値はmarkerである。

 
(setq m (point-marker))
     => #
(set-marker m 55)
     => #
(setq b (get-buffer "foo"))
     => #
(set-marker m 0 b)
     => #

Function: move-marker marker position &optional buffer
これはset-markerの別名である。



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

30.7 マーク

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=The%20Mark"
"texi/elisp21/マーク"へのコメント(無し)

各バッファの1つの特別なマーカをマーク(mark)として区別します。 これは、kill-regionindent-rigidlyなどのコマンド向けに ユーザーのために位置を記録するものです。 Lispプログラムでは、ユーザーが使う可能性のある値だけをマークに設定し、 プログラムの内部向けにはけっしてマークを使いません。 たとえば、コマンドreplace-regexpは、 置換を行うまえのポイント値をマークに設定します。 置換を完了したあとに、ユーザーが手軽にまえの位置に戻れるようにするためです。

多くのコマンドは、対話的に呼ばれるとポイントとマークのあいだの テキストに作用するように設計されています。 読者がそのようなコマンドを書くときには、 マークを直接検査しないでください。 そのかわりに、`r'を指定したinteractiveを使います。 こうすると、 対話的に呼ばれるとポイントとマークの値がコマンドの引数に与えられますが、 別のLispプログラムからは引数を明示できます。 See 節 20.2.2 interactiveのコード文字

各バッファには、他のバッファのマークの値とは独立な 独自のマークの値があります。 バッファが作成されると、マークは存在しますがどこも指さない状態です。 これを『バッファのマークは欠如している』状態とみなします。

バッファでいったんマークが『存在』するようになれば、 マークが存在しなくなることは普通はありません。 しかし、暫定マーク(transient-mark)モードをオンにすると、 マークが不活性になることはあります。 すべてのバッファでつねにバッファローカルな変数mark-activeが マークが活性かどうかを表します。 その値がnil以外であるとマークは活性です。 コマンドでdeactivate-marknil以外の値を設定すると、 エディタコマンドループに戻ったときにマークを不活性にするようにできます (ただし、暫定マーク(transient-mark)モードがオンの場合に限る)。

暫定マーク(transient-mark)モードを使う主な目的は、 マークが活性であるとこのモードはリージョンを強調表示するからです。 See 節 37. Emacsの画面表示

マークに加えて、各バッファにはマークリング(mark ring)、 つまり、マークの以前の値を保持したリストがあります。 編集コマンドがマークを変更すると、 通常、編集コマンドはマークの古い値をマークリングに保存します。 変数mark-ring-maxで、マークリングに収める要素の最大個数を指定します。 リストがこの長さに達すると、新たな要素を加えるたびに古い要素を削除します。

Function: mark &optional force
この関数は、カレントバッファのマーク位置を整数で返す。

マークが不活性であると、通常、markはエラーを通知する。 しかし、forcenil以外であるとmarkはマーク位置を返すが、 当該バッファでマークが設定されたことがなければnilを返す。

Function: mark-marker
この関数は、カレントバッファのマークを返す。 これは、Emacs内部のマーク位置を記録したマーカそのものであり、コピーではない。 したがって、このマーカの位置を変更すると、マークの位置に直接影響する。 この効果を望まない限り、そのようにしないこと。

 
(setq m (mark-marker))
     => #
(set-marker m 100)
     => #
(mark-marker)
     => #

他のマーカと同様に、このマーカは任意のバッファでポイントを指すようにできる。 マークが指しているバッファ以外のバッファ内位置を指すことは勧めない。 そのようにすると、一貫性はあるが妙な結果を生じる。

Function: set-mark position
この関数は、位置positionにマークを設定し、マークを活性にする。 マークの古い値はマークリングに保存しない

注意: ユーザーにマークが移動したことを示し、かつ、 まえのマーク位置を破棄したい場合にのみこの関数を使うこと。 通常、新たにマークを設定したときには、 古いマークをmark-ringに入れるべきである。 この理由から、ほとんどのアプリケーションでは、 set-markではなくpush-markpop-markを使うべきである。

Emacs Lispの初心者プログラマは、誤った目的にマークを使いがちである。 マークはユーザーの便宜のための位置を保存する。 編集コマンドは、 コマンドのユーザーレベルの機能の一部としてマークを変更する以外には、 マークを変更してはならない。 (変更する場合には、その効果を明文化しておくべきである。) Lispプログラムの内部で使う位置を記録するには、Lisp変数に保存する。 たとえばつぎのようにする。

 
(let ((beg (point)))
  (forward-line 1)
  (delete-region beg (point))).

Function: push-mark &optional position nomsg activate
この関数は、カレントバッファのマークをpositionとし、 以前のマークのコピーをmark-ringへ入れる。 positionnilであると、ポイントの値を使う。 push-marknilを返す。

関数push-markは、通常、マークを活性にしない。 活性にするには引数activatetを指定する。

nomsgnilであると、メッセージ`Mark set'を表示する。

Function: pop-mark
この関数は、mark-ringから先頭要素を取り出し、 そのマークをカレントバッファの実際のマークとする。 バッファのポイントは移動しない。 また、mark-ringが空であるとなにもしない。 マークを不活性にする。

戻り値に意味はない。

User Option: transient-mark-mode
この変数がnil以外であると 暫定マーク(transient-mark)モードがオンであるが、 バッファを変更する各基本関数はdeactivate-markに設定する。 つまり、バッファを変更するコマンドは、通常、マークを不活性にする。

User Option: mark-even-if-inactive
これがnil以外であると、 LispプログラムやEmacsユーザーは、マークが不活性であってもマークを使える。 このオプションは、暫定マーク(transient-mark)モードのふるまいに影響する。 このオプションがnil以外であると、 マークが不活性になるとリージョンの強調表示を止めるが、 マークを使うコマンドはマークが活性であるものとして動作する。

Variable: deactivate-mark
編集コマンドがこの変数にnil以外を設定すると、 エディタコマンドループは(暫定マーク(transient-mark)モードがオンであると) コマンドから戻るとマークを不活性にする。 コマンドが終了したらマークを不活性にするために、 バッファを変更するすべての基本関数はdeactivate-markに設定する。

Function: deactivate-mark
この関数は、暫定マーク(transient-mark)モードが オンであるとマークを不活性にする。 さもなければなにもしない。

Variable: mark-active
この変数がnil以外であると、マークは活性である。 この変数は各バッファにおいてつねにバッファローカルである。

Variable: activate-mark-hook
Variable: deactivate-mark-hook
これらのノーマルフックは、それぞれ、 マークが活性になったとき、不活性になったときに実行される。 マークが活性でありリージョンが変更されたときには、 フックactivate-mark-hookはコマンドの終りでも実行される。

Variable: mark-ring
このバッファローカルな変数の値は、 カレントバッファで保存したマークを最新のものから順に並べたリストである。

 
mark-ring
=> (# 
    #
    ...)

User Option: mark-ring-max
この変数の値は、mark-ringの最大の大きさである。 これより多くのマークをmark-ringに積むと、 push-markは新しいものを追加するときに古いものを削除する。



[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [表紙] [目次] [索引] [検索] [上端 / 下端]

30.8 リージョン

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=The%20Region"
"texi/elisp21/リージョン"へのコメント(無し)

ポイントとマークのあいだのテキストをリージョン(region)といいます。 さまざまな関数がポイントとマークで区切られたテキストに作用しますが、 リージョンそのものに特に関連した関数だけについてここで述べます。

Function: region-beginning
この関数は、リージョンの先頭の位置を(整数で)返す。 これは、ポイントかマークの小さいほうの位置である。

マークがどこも指していなければ、エラーを通知する。

Function: region-end
この関数は、リージョンの末尾の位置を(整数で)返す。 これは、ポイントかマークの大きいほうの位置である。

マークがどこも指していなければ、エラーを通知する。

関数region-beginningregion-endを使う必要がある プログラムはほとんどないはずです。 リージョンに作用するように設計されたコマンドは、 普通、`r'を指定したinteractiveを使って リージョンの先頭と末尾をみつけます。 これにより、Lispプログラムからは引数として境界を明示的に指定できます。 (See 節 20.2.2 interactiveのコード文字。)


[ << ] [ >> ]           [表紙] [目次] [索引] [検索] [上端 / 下端]