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

29. バッファ内の位置

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Positions"
"texi/elisp21/バッファ内の位置"へのコメント(無し)

バッファ内位置(position)は、 バッファ内のテキストの文字を添字付けします。 より正確にいえば、バッファ内位置は2つの文字のあいだの箇所 (あるいは、先頭文字ではそのまえ、最後の文字ではそのうしろ)を識別して、 指定位置のまえやうしろの文字を指定できるようにします。 しかし、しばしば位置『にある』文字といいますが、 これは位置の直後の文字を意味します。

バッファ内位置は、通常、1から始まる整数で表しますが、 マーカ(marker)で表すこともできます。 マーカは特別なオブジェクトであり、 テキストを挿入したり削除しても 同じ周りの文字に留まるように自動的に再配置されます。 See 節 30. マーカ



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

29.1 ポイント

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

ポイント(point)は、 自己挿入文字やテキスト挿入関数を含む多くの編集コマンドが使う バッファ内の特別な位置です。 他のコマンドは、バッファ内の別の箇所で編集したり挿入できるように ポイントをテキスト内で移動します。

他のバッファ内位置と同様に、ポイントは文字そのものではなく、 2つの文字のあいだの箇所 (あるいは、先頭文字ではそのまえ、最後の文字ではそのうしろ)を指定します。 通常、端末では、ポイントの直後の文字に重ねてカーソルを表示します。 ポイントはカーソルがある文字のまえに実際にはあります。

ポイントの値は、1からバッファのサイズ足す1です。 ナロイング(see 節 29.4 ナロイング)していると、 ポイントはバッファの参照可能な (バッファの端を含むかもしれない)範囲内に制限されます。

各バッファには独自のポイント値があり、 それは他のバッファのポイント値とは独立です。 各ウィンドウにも独自のポイント値があり、 同じバッファを表示している他のウィンドウのポイント値とは独立です。 このようなわけで、同じバッファを表示しているさまざまなウィンドウで 異なるポイント値を持てるのです。 1つのウィンドウだけにバッファが表示されているときには、 バッファのポイントとウィンドウのポイントは、通常、同じ値であり、 それらを区別することはほとんど重要ではありません。 詳しくは、See 節 27.9 ウィンドウとポイント

Function: point
この関数はカレントバッファのポイント値を整数で返す。

 
(point)
     => 175

Function: point-min
この関数は、カレントバッファで参照可能なポイント値の最小値を返す。 これは通常1であるが、 ナロイングしているときには、ナロイングした領域の開始位置である。 (see 節 29.4 ナロイング。)

Function: point-max
この関数は、カレントバッファで参照可能なポイント値の最大値を返す。 ナロイングしていなければ、これは(1+ (buffer-size))である。 ナロイングしているときには、ナロイングした領域の終了位置である。 (see 節 29.4 ナロイング。)

Function: buffer-end flag
この関数は、flagが1未満であれば(point-min)を返し、 さもなければ(point-max)を返す。 引数flagは整数であること。

Function: buffer-size
この関数は、カレントバッファ内の総文字数を返す。 ナロイング(see 節 29.4 ナロイング)していなければ、 point-maxはこの値より1大きな値を返す。

 
(buffer-size)
     => 35
(point-max)
     => 36



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

29.2 移動

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

移動関数は、現在のポイント値やバッファの先頭や末尾を基準にして、 あるいは、選択されているウィンドウの端を基準にして、 ポイント値を変更します。 See 節 29.1 ポイント

29.2.1 文字単位の移動    Moving in terms of characters.
29.2.2 単語単位の移動    Moving in terms of words.
29.2.3 バッファの両端への移動    Moving to the beginning or end of the buffer.
29.2.4 テキスト行単位の移動    Moving in terms of lines of text.
29.2.5 スクリーン行分の移動    Moving in terms of lines as displayed.
29.2.6 式単位の移動    Moving by parsing lists and sexps.
29.2.7 文字群の飛び越し    Skipping characters belonging to a certain set.



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

29.2.1 文字単位の移動

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Character%20Motion"
"texi/elisp21/文字単位の移動"へのコメント(無し)

これらの関数は、文字数に基づいてポイントを移動します。 goto-charが基本になる基本関数であり、他の関数はこれを使っています。

コマンド: goto-char position
この関数は、カレントバッファのポイント位置を値positionとする。 positionが1未満であると、バッファの先頭にポイントを移動する。 positionがバッファの長さより大きい場合には、 バッファの末尾にポイントを移動する。

ナロイングしている場合であっても、 positionはバッファの先頭から数えるが、 参照可能部分の外側にはポイントは移動できない。 positionが範囲外であると、 goto-charは参照可能部分の先頭か末尾にポイントを移動する。

この関数を対話的に呼び出すと、 前置引数があればpositionは数値前置引数である。 さもなければミニバッファから読む。

goto-charpositionを返す。

コマンド: forward-char &optional count
この関数は、前方へ、つまり、バッファの末尾に向けて (countが負であれば、後方へ、つまり、バッファの先頭へ向けて) count文字分ポイントを移動する。 バッファの先頭や末尾を越えて (ナロイングしているときには参照可能部分を越えて) ポイントを移動しようとすると、 beginning-of-bufferend-of-bufferのエラーコードで エラーを通知する。

対話的に呼び出されると、countは数値前置引数である。

コマンド: backward-char &optional count
この関数は、後方へ、つまり、バッファの先頭に向けて (countが負であれば、前方へ、つまり、バッファの末尾へ向けて) count文字分ポイントを移動する。 バッファの先頭や末尾を越えて (ナロイングしているときには参照可能部分を越えて) ポイントを移動しようとすると、 beginning-of-bufferend-of-bufferのエラーコードで エラーを通知する。

対話的に呼び出されると、countは数値前置引数である。



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

29.2.2 単語単位の移動

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Word%20Motion"
"texi/elisp21/単語単位の移動"へのコメント(無し)

これらの単語を解析する関数は、 当該文字が単語の一部かどうかを判定するために構文テーブルを使います。 See 節 34. 構文テーブル

コマンド: forward-word count
この関数は、前方へ(countが負ならば後方へ) count単語分ポイントを移動する。 『1単語分移動する』とは、 単語構成文字を越えてから単語区切り文字(あるいはバッファの参照可能部分の 境界)に出会うまでポイントを移動することを意味する。

バッファの境界で止まらず(最後の単語は除く)に count単語分移動できると、値はtである。 さもなければ値はnilであり、ポイントはバッファの境界で止まる。

対話的に呼び出されると、countは数値前置引数である。

コマンド: backward-word count
この関数はforward-wordと同様であるが、 前方へではなく後方へ単語の先頭に出会うまで移動する。

対話的に呼び出されると、countは数値前置引数である。

この関数は、プログラムではほとんど使われない。 負の引数でforward-wordを呼び出すほうが効率的だからである。

Variable: words-include-escapes
この変数は、forward-wordとそれを使うもののふるまいに影響する。 nil以外であると、『エスケープ』や『文字クォート』の 構文クラスに属する文字も単語の一部とみなす。 さもなければ、単語の一部とはみなさない。



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

29.2.3 バッファの両端への移動

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Buffer%20End%20Motion"
"texi/elisp21/バッファの両端への移動"へのコメント(無し)

バッファの先頭にポイントを移動するには、つぎのように書きます。

 
(goto-char (point-min))

同様に、バッファの末尾に移動するには、つぎのようにします。

 
(goto-char (point-max))

上のことを行うためにユーザーが使うコマンドが2つあります。 これらはマークを設定してエコー領域にメッセージを表示するので、 これらをLispプログラムからは使わないように警告しておきます。

コマンド: beginning-of-buffer &optional n
この関数は、バッファ(あるいはナロイングしているときには参照可能部分) の先頭にポイントを移動し、移動前の位置にマークを設定する。 nnil以外であると、 バッファの先頭から10分のnの箇所にポイントを移動する。

対話的に呼び出すと、前置引数があればnは数値前置引数である。 さもなければnのデフォルトはnilである。

警告: Lispプログラムではこの関数を使わないこと!

コマンド: end-of-buffer &optional n
この関数は、バッファ(あるいはナロイングしているときには参照可能部分) の末尾にポイントを移動し、移動前の位置にマークを設定する。 nnil以外であると、 バッファの末尾から10分のnの箇所にポイントを移動する。

対話的に呼び出すと、前置引数があればnは数値前置引数である。 さもなければnのデフォルトはnilである。

警告: Lispプログラムではこの関数を使わないこと!



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

29.2.4 テキスト行単位の移動

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Text%20Lines"
"texi/elisp21/テキスト行単位の移動"へのコメント(無し)

テキスト行とは、改行文字で区切られたバッファの部分です。 改行文字はまえの行に属するとみなします。 最初のテキスト行がバッファの先頭から始まり、 バッファの末尾の文字が改行であってもなくても、 最後のテキスト行はバッファの末尾で終ります。 バッファをテキスト行に分割することは、 ウィンドウの幅、表示上の行の継続、タブやコントロール文字の表示方法には 影響されません。

コマンド: goto-line line
この関数は、バッファの先頭を1行目と数えてline行目の先頭に ポイントを移動する。 lineが1未満であると、バッファの先頭へポイントを移動する。 lineがバッファ内の行数より大きいと、 バッファの末尾、つまり、バッファの最後の行の末尾にポイントを移動する。 これは、goto-lineが行頭にポイントを移動しない唯一の場面である。

ナロイングしているときでも、 lineはバッファの先頭から数えるが、 参照可能部分の外側にはポイントは移動しない。 したがって、行番号が参照不可な部分を指定するときには、 goto-lineは参照可能部分の先頭か末尾へポイントを移動する。

goto-lineの戻り値は、 (ナロイングを考慮せずにバッファ全体でみた) lineと実際のポイントの移動先の行の行番号との差である。 したがって、指定した行に達するまえにバッファの末尾に出会うと値は正である。 バッファの実際の末尾にではなく参照可能部分の末尾に出会うと値は0である。

対話的に呼び出すと、 前置引数があればlineは数値前置引数である。 さもなければlineをミニバッファから読む。

コマンド: beginning-of-line &optional count
この関数は、現在行の先頭にポイントを移動する。 引数countnilでも1でもないと、 count-1行だけ前方へ移動してから行頭に移動する。

バッファ(ナロイングしているときには参照可能部分)の末尾に達すると ポイントをそこへ移動する。 エラーは通知しない。

コマンド: end-of-line &optional count
この関数は、現在行の末尾にポイントを移動する。 引数countnilでも1でもないと、 count-1行だけ前方へ移動してから行末に移動する。

バッファ(ナロイングしているときには参照可能部分)の末尾に達すると ポイントをそこへ移動する。 エラーは通知しない。

コマンド: forward-line &optional count
この関数は、count行前方の行頭にポイントを移動する。 countが負であると、 -count行後方の行頭にポイントを移動する。 countが0であると、現在行の先頭にポイントを移動する。

指定行数だけ移動するまえに バッファ(ナロイングしているときには参照可能部分)の先頭や末尾に達すると ポイントをそこへ移動する。 エラーは通知しない。

forward-lineは、 countと実際に移動した行数の差を返す。 3行しかないバッファの先頭で5行前方へ移動しようとすると、 ポイントは最後の行の末尾で止まり、値は2になる。

対話的に呼び出すと、countは数値前置引数である。

Function: count-lines start end
この関数は、カレントバッファのstartendの あいだの部分にある行の行数を返す。 startendが等しければ0を返す。 さもなければ、startendが同じ行にある場合であっても 少なくとも1を返す。 というのは、それらのあいだのテキストは孤立しているとみなされ、 空でなければ少なくとも1行はあるはずだからである。

count-linesの使用例を示す。

 
(defun current-line ()
  "Return the vertical position of point..."
  (+ (count-lines (window-start) (point))
     (if (= (current-column) 0) 1 0)
     -1))

31.1 ポイント付近のテキストを調べるの関数bolpeolpも参照してください。 これらの関数はポイントを移動しませんが、ポイントがすでに行の先頭や末尾に あるかどうかを検査します。



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

29.2.5 スクリーン行分の移動

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Screen%20Lines"
"texi/elisp21/スクリーン行分の移動"へのコメント(無し)

前節の行単位の関数は、改行文字で区切られたテキスト行だけを数えます。 対照的に、これらの関数は、スクリーン上にどのようにテキストが現れるかで 定義されるスクリーン上の行を数えます。 テキスト行が選択されているウィンドウの幅に収まるだけ短ければ、 1テキスト行は1スクリーン行ですが、 しかし、それ以外では1テキスト行は複数のスクリーン行を占めます。

テキスト行を複数のスクリーン行に継続せずに スクリーン上で切り詰める場合もあります。 このような場合、vertical-motionは、 forward-lineによく似たポイントの移動を行います。 See 節 37.2 表示の切り詰め

与えられた文字列の幅は、各文字の見ためを制御するフラグに依存するので、 vertical-motionは、 テキストを収めたバッファや選択されているウィンドウ (その幅や切り詰めフラグ、ウィンドウごとに異なりうる表示テーブルが あるため)に依存して、特定のテキスト部分に対して異なったふるまいをします。 See 節 37.13 通常の画面表示慣習

これらの関数は、スクリーン行がどこで区切れるかを決定するためにテキストを走査 するので、走査する量に比例して時間がかかります。 読者がこれらを多用する意図があるときには、 読者のコードの効率を改善するキャッシュをEmacsが提供します。 See 節 cache-long-line-scans

Function: vertical-motion count &optional window
この関数は、ポイントを含むスクリーン行から countスクリーン行数だけ下向きにポイントを移動する。 countが負であると上向きに移動する。

vertical-motionは、ポイントを移動したスクリーン行数を返す。 バッファの先頭や末尾に達すると、 この値は絶対値ではcountより小さい。

ウィンドウwindowは、 幅、水平スクロール、表示テーブルなどのパラメータを得るために使われる。 しかし、windowに別のバッファが表示されているとしても、 vertical-motionはつねにカレントバッファに作用する。

コマンド: move-to-window-line count
この関数は、選択されているウィンドウに現在表示されているテキストに 基づいてポイントを移動する。 ウィンドウの先頭からcountスクリーン行の先頭にポイントを移動する。 countが負であると、底(あるいはバッファの末尾がスクリーンの 底より上にある場合にはバッファの最終行)から数えて -countスクリーン行位置を指定する。

countnilであると、 ウィンドウの中央の行の先頭にポイントを移動する。 count の絶対値がウィンドウのサイズよりも大きいときには、 ウィンドウに十分な高さがあった場合に移動するであろう スクリーン行の箇所にポイントを移動する。 そのため、スクロールして当該箇所がスクリーンに現れるように再表示する。

対話的に呼び出されると、countは数値前置引数である。

戻り値は、ウィンドウの先頭行を0と数えて、移動先の行のウィンドウ行番号である。

Function: compute-motion from frompos to topos width offsets window
この関数は、スクリーン上での位置を計算しながらカレントバッファを走査する。 バッファ内位置fromがスクリーン座標fromposに対応すると仮定して、 fromから前方へ向けてtotoposのどちらかに 達するまでバッファを走査する。 バッファ内の終了位置とスクリーン座標を返す。

座標引数frompostoposは、 (hpos . vpos)の形のコンスセルである。

引数widthは、テキストを表示できるコラム数であり、 これは継続行の扱いに影響する。 読者が選んだウィンドウに対してwindow-widthが返した値、 つまり、通常、(window-width window)を使う。

引数offsetsは、nilであるか、 (hscroll . tab-offset)の形のコンスセルである。 ここで、hscrollは左端に表示されていないコラム数であり、 多くの場合はwindow-hscrollを呼び出して得た値を使う。 一方、tab-offsetはスクリーン上でのコラム番号と バッファ内でのコラム番号の差である。 この値は、継続行においてまえのスクリーン行の幅がtab-widthで終らない 場合に0以外になる。 継続しない行ではつねに0である。

ウィンドウwindowは、使用する表示テーブルを指定するためだけに使われる。 windowに表示されているバッファに関わらず、 compute-motionはつねにカレントバッファに作用する。

戻り値は、5要素のリストである。

 
(pos vpos hpos prevhpos contin)

ここで、posは走査を終えたバッファ内位置であり、 vposは垂直方向のスクリーン位置、 hposは水平方向のスクリーン位置である。

結果のprevhposは、posから1文字分戻った箇所の水平位置である。 この文字のあとで最終行が継続しているときには、 結果のcontintである。

たとえば、あるウィンドウのlineスクリーン行のcolコラムに 対応するバッファ内位置を探すには、 fromとしてウィンドウの表示開始位置、 fromposとしてウィンドウの左上隅の座標を渡します。 toにはバッファの(point-max)を渡して 走査をバッファの参照可能部分のみに制限し、 toposとしてlinecolを渡す。 つぎのように呼び出す。

 
(defun coordinates-of-position (col line)
  (car (compute-motion (window-start)
                       '(0 . 0)
                       (point-max)
                       (cons col line)
                       (window-width)
                       (cons (window-hscroll) 0)
                       (selected-window))))

ミニバッファに対してcompute-motionを使うときには、 minibuffer-prompt-widthを使って 最初のスクリーン行の先頭の水平位置を得る必要がある。 see 節 19.9 ミニバッファに関するその他



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

29.2.6 式単位の移動

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=List%20Motion"
"texi/elisp21/式単位の移動"へのコメント(無し)

ここでは、釣り合った括弧で囲まれた式 (Emacs内でそれらを単位に移動するときにはS式(sexps)とも呼ばれる)を 扱う関数について述べます。 構文テーブルは、これらの関数がさまざまな文字を どのように解釈するかを制御します。 34. 構文テーブルを参照してください。 S式やその一部を走査する下位レベルの基本関数については、 See 節 34.6 釣り合った式の解析。 ユーザーレベルのコマンドに関しては、 GNU Emacs マニュアルを参照してください。

コマンド: forward-list arg
この関数は、釣り合った括弧で囲まれたものをarg個前方へ飛び越えて移動する。 (単語や文字列のクォート対などの他の構文要素は無視する。)

コマンド: backward-list arg
この関数は、釣り合った括弧で囲まれたものをarg個後方へ飛び越えて移動する。 (単語や文字列のクォート対などの他の構文要素は無視する。)

コマンド: up-list arg
この関数は、前方へ向けてarg個の括弧のレベルを抜ける。 負の引数では後方へ向けて浅いレベルへ移動する。

コマンド: down-list arg
この関数は、前方へ向けてarg個の括弧のレベルだけ深く入る。 負の引数では後方へ向けて括弧の深い(-arg)レベルへ移動する。

コマンド: forward-sexp arg
この関数は、arg個の釣り合った式を前方へ向けて飛び越えて移動する。 釣り合った式には、括弧で区切られたものに加えて、 単語や文字列定数などの他の種類も含まれる。 たとえばつぎのとおり。

 
---------- Buffer: foo ----------
(concat-!- "foo " (car x) y z)
---------- Buffer: foo ----------

(forward-sexp 3)
     => nil

---------- Buffer: foo ----------
(concat "foo " (car x) y-!- z)
---------- Buffer: foo ----------

コマンド: backward-sexp arg
この関数は、arg個の釣り合った式を後方へ向けて飛び越えて移動する。

コマンド: beginning-of-defun arg
この関数は、前方へ向けてarg個目の関数定義の先頭へ移動する。 argが負であると、後方へ向けて、 関数定義の末尾ではなく関数定義の先頭へ移動する。

コマンド: end-of-defun arg
この関数は、前方へ向けてarg個目の関数定義の末尾へ移動する。 argが負であると、後方へ向けて、 関数定義の先頭ではなく関数定義の末尾へ移動する。

User Option: defun-prompt-regexp
この変数がnil以外であると、 関数定義を始める開き括弧のまえに現れうるテキストを指定する正規表現を保持する。 つまり、関数定義は、 行の先頭がこの正規表現に一致するテキストで始まり、 それに開き括弧の構文に属する文字が続く行で始まる。



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

29.2.7 文字群の飛び越し

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Skipping%20Characters"
"texi/elisp21/文字群の飛び越し"へのコメント(無し)

つぎの2つの関数は、指定した種類の文字を飛び越えてポイントを移動します。 たとえば、白文字を飛び越すためにこれらはしばしば使われます。 関連する関数については、34.5 移動と構文を参照してください。

Function: skip-chars-forward character-set &optional limit
この関数は、指定した文字の集まりを飛び越えて、 カレントバッファ内で前方にポイントを移動する。 ポイントのあとの文字を調べ、 その文字がcharacter-setに一致するとポイントを進める。 これをcharacter-setに一致しない文字に達するまで繰り返す。 この関数は飛び越えた文字の個数を返す。

引数character-setは、正規表現の`[...]'の内側と同じであるが、 `]'は特別扱いせず、`\'は`^'や`-'や`\'をクォートする。 したがって、"a-zA-Z"はすべての英文字を飛び越えて 最初の英文字でない文字のまえで止まる。 "^a-zA-Z"は英文字でない文字を飛び越えて最初の英文字で止まる。 see 節 33.2 正規表現。

limitを指定すると(数かマーカであること)、 ポイントを移動できるバッファ内の最大位置を指定する。 ポイントは、limitで止まるかlimitに達するまえに止まる。

つぎの例では、ポイントは最初は`T'の直前に位置している。 フォームを評価後には、ポイントはその行末 (`hat'の`t'と改行のあいだ)に位置している。 この関数は、すべての英文字と空白を飛び越えるが、改行は飛び越えない。

 
---------- Buffer: foo ----------
I read "-!-The cat in the hat
comes back" twice.
---------- Buffer: foo ----------

(skip-chars-forward "a-zA-Z ")
     => nil

---------- Buffer: foo ----------
I read "The cat in the hat-!-
comes back" twice.
---------- Buffer: foo ----------

Function: skip-chars-backward character-set &optional limit
この関数は、limitに達するまで、 後方へ向かってcharacter-setに一致する文字を飛び越えてポイントを移動する。 これはskip-chars-forwardと同様であるが、移動方向が異なる。

移動距離を表す値を返す。 それは0以下の整数である。



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

29.3 エクスカージョン

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Excursions"
"texi/elisp21/エクスカージョン"へのコメント(無し)

プログラムの局所的な部分で『一時的に』ポイントを移動したり、 一時的にバッファを切り替えられるとしばしば有用です。 これをエクスカージョン(excursion、周遊)と呼び、 スペシャルフォームsave-excursionで行います。 この構文は、カレントバッファとそのポイントやマーカの値を保存し、 エクスカージョンの完了後にそれらを復元します。

ウィンドウの構成を保存したり復元するフォームは、 別のところで述べてあります (27.16 ウィンドウ構成とsee 節 28.12 フレーム構成)。

Special Form: save-excursion forms...
スペシャルフォームsave-excursionは、 カレントバッファの識別子とそのポイントやマーカの値を保存し、 formsを評価し、最後に、 バッファと保存しておいたポイントやマーカの値を復元する。 throwやエラーによる異常脱出(see 節 9.5 非ローカル脱出)であっても、 これらの保存した値を復元する。

スペシャルフォームsave-excursionは、 プログラムの一部分だけでバッファやポイントを移動し プログラムの他の部分への影響を防ぐ標準的な方法である。 EmacsのLispソースでは4000回以上も使われている。

save-excursionは他のバッファのポイントやマークの値は保存しないので、 他のバッファでの変更はsave-excursionから抜けても持続する。

同様に、save-excursionは、 switch-to-bufferなどの関数で変更された ウィンドウとバッファの対応関係は復元しない。 これらの対応関係や選択されているウィンドウを復元する1つの方法は、 save-excursionの内側でsave-window-excursionを 使うことである(see 節 27.16 ウィンドウ構成)。

save-excursionの戻り値は、formsの最後の結果であるか、 formsを与えなければnilである。

 
(save-excursion forms)
==
(let ((old-buf (current-buffer))
      (old-pnt (point-marker))
      (old-mark (copy-marker (mark-marker))))
  (unwind-protect
      (progn forms)
    (set-buffer old-buf)
    (goto-char old-pnt)
    (set-marker (mark-marker) old-mark)))

警告: 保存されたポイント値の箇所に 普通にテキストを挿入すると、すべてのマーカを再配置するように 保存されたポイント値を再配置する。 したがって、保存されたポイント値が復元されると、 ポイントは挿入されたテキストのまえに普通どおりにくる。

save-excursionはマーカの位置を保存しますが、 バッファを変更する関数がdeactivate-markを行うことを防ぎませんから、 コマンドが終了するとマーカが不活性になってしまいます。 See 節 30.7 マーク



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

29.4 ナロイング

URL="https://bookshelf.jp/cgi-bin/goto.cgi?file=elisp21&node=Narrowing"
"texi/elisp21/ナロイング"へのコメント(無し)

ナロイング(narrowing)とは、 Emacsの編集コマンドが参照できるテキストを バッファの制限された文字の範囲に限定することです。 参照できるテキストのことをバッファの 参照可能部分(accessible portion)と呼びます。

ナロイングは、参照可能部分の先頭と末尾になる2つのバッファ内位置で指定します。 ほとんどの編集コマンドやほとんどのEmacs基本関数にとっては、 これらの位置はバッファの先頭や末尾の値を置き換えることになります。 ナロイングしていると、参照可能部分の外側のテキストは表示されませんし、 ポイントは参照可能部分の外側へは移動できません。

通常はバッファの先頭から数える位置や行番号などの値は ナロイングしていても同様に数えますが、 それらを使う関数は参照できないテキストを操作することを拒否します。

バッファを保存するコマンドはナロイングの影響を受けません。 つまり、ナロイングに関係なくバッファ全体を保存します。

コマンド: narrow-to-region start end
この関数は、カレントバッファのstartで始まりendで終る部分を 参照可能部分にする。 どちらの引数も文字の位置であること。

対話的に呼び出されると、startendは 現在のリージョンの境界(ポイントとマークの小さいほうがさきにくる)である。

コマンド: narrow-to-page move-count
このコマンドは、カレントバッファの参照可能部分を 現在のページのみを含むようにする。 省略可能な第1引数move-countnil以外であると、 move-countページだけ前方か後方へ移動してから 1ページ分にナロイングする。 変数page-delimiterがページの開始箇所と終了箇所を指定する (see 節 33.8 編集に用いられる標準的な正規表現)。

対話的に呼び出されると、move-countは数値前置引数である。

コマンド: widen
この関数は、カレントバッファのナロイングを解除し、 全体を参照できるようにする。 これをワイドニング(widening)と呼ぶ。 これはつぎの式と等価である。

 
(narrow-to-region 1 (1+ (buffer-size)))

Special Form: save-restriction body...
このスペシャルフォームは、現在の参照可能部分の境界を保存し、 フォームbodyを評価し、最後に、保存した境界を復元して まえと同じナロイング状態(あるいはナロイングなし)に復元する。 throwやエラーによる異常脱出(see 節 9.5 非ローカル脱出)であっても、 ナロイング状態を復元する。

save-restrictionの戻り値は、bodyの最後の結果であるか、 bodyを与えなければnilである。

注意: 構文save-restrictionを使うときには まちがいやすい。 使うまえにこの説明全体を読むこと。

bodyでカレントバッファを切り替えても save-restrictionはもとのバッファ(バッファの制限を保存したバッファ)に 制限を復元するが、もとのカレントバッファには戻さない。

save-restrictionはポイントやマークは復元しない。 それにはsave-excursionを使う。 save-restrictionsave-excursionの両者を 一緒に使うときには、save-excursionが先に(外側に)くること。 さもないと、古いポイント値は一時的なナロイングが有効な状態で復元される。 古いポイント値が一時的なナロイングの範囲外にあると正しく復元できない。

スペシャルフォームsave-restrictionは、 参照可能部分の先頭と末尾をバッファの先頭と末尾からの距離として記録する。 いいかえれば、参照可能部分の前後の参照できないテキストの量を記録する。

この方法は、bodyでさらにナロイングしても正しい結果を生じる。 しかし、bodyでワイドニングして保存されているナロイングの範囲外を 変更するとsave-restrictionが混乱する。 このようにしたいときには、 save-restrictionは正しい解法ではない。 つぎのようにする必要がある。

 
(let ((beg (point-min-marker))
      (end (point-max-marker)))
  (unwind-protect
      (progn body)
    (save-excursion
      (set-buffer (marker-buffer beg))
      (narrow-to-region beg end))))

save-restrictionの正しい使い方の簡単な例を示す。

 
---------- Buffer: foo ----------
This is the contents of foo
This is the contents of foo
This is the contents of foo-!-
---------- Buffer: foo ----------

(save-excursion
  (save-restriction
    (goto-char 1)
    (forward-line 2)
    (narrow-to-region 1 (point))
    (goto-char (point-min))
    (replace-string "foo" "bar")))

---------- Buffer: foo ----------
This is the contents of bar
This is the contents of bar
This is the contents of foo-!-
---------- Buffer: foo ----------

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