GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/elisp/Recombining-Windows.html ・ emacs-doc.conao3.com

29.9 ウィンドウの再結合

ウィンドウ W の最後の兄弟要素を削除すると、その親ウィンドウも同時に削除され、ウィンドウツリー内では W がそれに取って代わります。つまり、W を親の兄弟要素と再結合して、新しいウィンドウの組み合わせを形成する必要があります(ウィンドウとフレーム を参照)。場合によっては、アクティブなウィンドウを削除することで、2つの内部ウィンドウまでもが削除されることがあります。

     ______________________________________
    | ______  ____________________________ |
    ||      || __________________________ ||
    ||      ||| ___________  ___________ |||
    ||      ||||           ||           ||||
    ||      ||||____W6_____||_____W7____||||
    ||      |||____________W4____________|||
    ||      || __________________________ ||
    ||      |||                          |||
    ||      |||                          |||
    ||      |||____________W5____________|||
    ||__W2__||_____________W3_____________ |
    |__________________W1__________________|

この構成においてW5を削除すると、通常はW3とW4も削除されます。残ったアクティブなウィンドウW2、W6、W7は再結合され、親W1を持つ新たな水平組み合わせを形成します。

しかし、W4のような親ウィンドウを削除しない方が適切な場合もあります。特に、同一タイプの組み合わせの中に埋め込まれた組み合わせを保持するために使用された親ウィンドウは、削除すべきではありません。このような埋め込みは、ウィンドウを分割し、その後新しいウィンドウを削除した際に、Emacsが関連フレームのレイアウトを分割前の状態に復元することを確実にするために有効です。

2つのアクティブウィンドウ W2 と W3、およびそれらの親 W1 から始まるシナリオを考えます。

     ______________________________________
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||_________________W2_________________||
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||_________________W3_________________||
    |__________________W1__________________|

次のように W2 を分割して、新しいウィンドウ W4 を作成します。

     ______________________________________
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||_________________W2_________________||
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||_________________W4_________________||
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||_________________W3_________________||
    |__________________W1__________________|

さて、ウィンドウを垂直方向に拡大する際、Emacsは下位のウィンドウが存在する場合、そこから対応する領域を確保しようとします。今回のケースでは、W4を拡大するとW3から領域が奪われることになります。

     ______________________________________
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||_________________W2_________________||
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||_________________W4_________________||
    | ____________________________________ |
    ||_________________W3_________________||
    |__________________W1__________________|

W4を削除すると、W3から先に奪っていた領域も含め、その領域全体がW2に割り当てられるようになります。

     ______________________________________
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||_________________W2_________________||
    | ____________________________________ |
    ||_________________W3_________________||
    |__________________W1__________________|

これは直感に反する場合があります。特に、W4 をバッファの一時的な表示にのみ使用し(一時的な表示 を参照)、初期レイアウトのまま作業を続けたい場合などです。

W2を分割する際に新しい親ウィンドウを作成することで、この挙動を修正できます。次に説明する変数を使えば、それが可能です。

ユーザーオプション: window-combination-limit

この変数は、ウィンドウを分割した際に新しい親ウィンドウを作成するかどうかを制御します。以下の値が指定可能です。

nil

つまり、新しいライブウィンドウは、既存の親ウィンドウが存在する場合、そのウィンドウが既存のウィンドウ構成と同じ方向に分割される限り、親ウィンドウを共有できるということです(そうでない場合は、いずれにせよ新しい内部ウィンドウが作成されます)。

window-size

つまり、display-buffer はウィンドウを分割する際に新しい親ウィンドウを作成し、alist 引数に window-height または window-width のエントリが渡されます(バッファ表示用のアクション関数 を参照)。それ以外の場合、ウィンドウ分割は nil の値と同様に動作します。

temp-buffer-resize

この場合、with-temp-buffer-window はウィンドウを分割する際に新しい親ウィンドウを作成し、temp-buffer-resize-mode が有効になります(一時表示を参照)。それ以外の場合、ウィンドウの分割は nil と同様に動作します。

temp-buffer

この場合、with-temp-buffer-window は既存のウィンドウを分割する際に常に新しい親ウィンドウを作成します(一時表示を参照)。それ以外の場合、ウィンドウの分割は nil と同様に動作します。

display-buffer

つまり、display-buffer(バッファ表示用のウィンドウの選択を参照)がウィンドウを分割する場合、常に新しい親ウィンドウが作成されます。それ以外の場合、ウィンドウの分割はnilと同様に動作します。

t

つまり、ウィンドウを分割すると常に新しい親ウィンドウが生成される。したがって、この変数の値が常に t であれば、いかなる時点においてもすべてのウィンドウツリーは二分木(ルートウィンドウを除く各ウィンドウがちょうど1つの兄弟を持つ木)となる。

デフォルトは window-size です。その他の値は将来の使用のために予約されています。

この変数の設定により、split-window が新しい親ウィンドウを作成した場合、新たに作成された内部ウィンドウに対しても set-window-combination-limit(後述)を呼び出します。これにより、子ウィンドウが削除された際のウィンドウツリーの再編成方法に影響が生じます(後述)。

window-combination-limit が t である場合、本シナリオの初期構成で W2 を分割すると、次のような結果になったはずです:

     ______________________________________
    | ____________________________________ |
    || __________________________________ ||
    |||                                  |||
    |||________________W2________________|||
    || __________________________________ ||
    |||                                  |||
    |||________________W4________________|||
    ||_________________W5_________________||
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||_________________W3_________________||
    |__________________W1__________________|

新しい内部ウィンドウ W5 が作成されました。その子は W2 と新しいライブウィンドウ W4 です。ここで、W2 は W4 の唯一の兄弟となるため、W4 を拡大すると W2 が縮小されようとし、W3 は影響を受けません。なお、W5 は、垂直方向の組み合わせ W1 に埋め込まれた2つのウィンドウの垂直方向の組み合わせを表しています。

関数: set-window-combination-limit window limit

この関数は、ウィンドウ window の 組み合わせ制限 を limit に設定します。この値は関数 window-combination-limit で取得可能です。効果については以下を参照してください。なお、これは内部ウィンドウに対してのみ有効です。split-window 関数は、呼び出し時に変数 window-combination-limit の値が t である場合、t を limit として渡してこの関数を自動的に呼び出します。

関数: window-combination-limit window

この関数は、window の組み合わせ上限を返します。

コンビネーション制限が意味を持つのは、内部ウィンドウの場合のみです。これが nil である場合、ウィンドウの削除に応じて、Emacs は window を自動的に削除し、window の子ウィンドウをその兄弟ウィンドウとグループ化して新しいウィンドウコンビネーションを形成することが許可されます。コンビネーション制限が t である場合、window の子ウィンドウが兄弟ウィンドウと自動的に再結合されることはありません。

本節の冒頭に示した構成において、W4(W6およびW7の親ウィンドウ)の組み合わせ制限がtである場合、W5を削除してもW4が暗黙的に削除されることはありません。

あるいは、いずれかのウィンドウが分割または削除された際に、常に同じ組み合わせのすべてのウィンドウをリサイズすることで、上述の問題を回避できます。これにより、本来であればこのような操作には小さすぎるウィンドウを分割することも可能になります。

ユーザーオプション: window-combination-resize

この変数が nil の場合、split-window がウィンドウ(window で表される)を分割できるのは、window の画面領域が自身と新しいウィンドウの両方を収めるのに十分な広さがある場合に限られます。

この変数が t の場合、split-window は新しいウィンドウを収めるため、window と同じ組み合わせに属するすべてのウィンドウのサイズ変更を試みます。特にこれにより、window が固定サイズのウィンドウであったり、通常では分割できないほど小さかったりする場合でも、split-window が成功する可能性があります。さらに、その後 window のサイズ変更や削除を行うと、その組み合わせに属する他のすべてのウィンドウのサイズが変更される場合があります。

デフォルト値は nil です。その他の値は将来の使用のために予約されています。特定の分割操作において、window-combination-limit の値が nil 以外である場合、この変数の値は無視されることがあります。

split-window の呼び出しを連続して行い、フレーム上に特定の事前定義済みウィンドウレイアウトを生成したい場合は、この変数を一時的に nil にバインドしてください。window-state-put(ウィンドウ構成 を参照)およびウィンドウレイアウトを変更する関数(ウィンドウレイアウトの変更 を参照)は、フレームの以前のレイアウトや体系的に変更されたレイアウトを復元するために、この処理を行います。

window-combination-resizeの効果を説明するために、以下のフレームレイアウトを考えてみましょう。

     ______________________________________
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||_________________W2_________________||
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||_________________W3_________________||
    |__________________W1__________________|

window-combination-resize が nil の場合、ウィンドウ W3 を分割しても W2 のサイズは変わりません:

     ______________________________________
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||_________________W2_________________||
    | ____________________________________ |
    ||                                    ||
    ||_________________W3_________________||
    | ____________________________________ |
    ||                                    ||
    ||_________________W4_________________||
    |__________________W1__________________|

window-combination-resize が t である場合、代わりに W3 を分割すると、3つのライブウィンドウすべてがほぼ同じ高さになります:

     ______________________________________
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||_________________W2_________________||
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||_________________W3_________________||
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||_________________W4_________________||
    |__________________W1__________________|

アクティブウィンドウ W2、W3、または W4 のいずれかを削除すると、その領域は残りの2つのアクティブウィンドウに比例配分されます。

以下の2つの関数を使用すると、隣接する複数のウィンドウに対して明示的に新しい親ウィンドウを作成したり、その操作を取り消したりすることができます。

関数: combine-windows first last

この関数は、firstからlastまで(両端を含む)のウィンドウを結合します。firstとlastは、同一の組み合わせにおける有効なウィンドウ、すなわち同じ親ウィンドウを持つウィンドウである必要があります。firstに前のウィンドウがなく、かつlastに次の兄弟ウィンドウがない場合、その親ウィンドウを返します。それ以外の場合は、最初の子ウィンドウをfirst、最後の子ウィンドウをlastとする新しい親ウィンドウを作成し、その親ウィンドウをfirstから始まりlastで終わるウィンドウに代わってウィンドウツリーに挿入し、新しい親ウィンドウを返します。

この関数は、同一の親ウィンドウに属する複数の兄弟ウィンドウをまとめて操作する際に便利です。横に並んだ3つの兄弟ウィンドウ w1、w2、w3 を考えてみましょう。w1 と w2 の下にはウィンドウを作成し、w3 の下には作成しないようにするには、まずこの関数を使って w1 と w2 を結合し、次にその結果得られたウィンドウを分割します。また、combine-windows の戻り値に対して window-state-get(ウィンドウ構成 を参照)を呼び出すことで、w1 と w2 の結合状態を取得することもできます。

関数: uncombine-window window

この関数は、指定された window の組み合わせを解除します。window は、その親ウィンドウが同タイプの内部ウィンドウである内部ウィンドウである必要があります。つまり、window とその親は、ともに水平方向または垂直方向のウィンドウの組み合わせである必要があります。この条件を満たす場合、関数は window の子ウィンドウを window の親の子ウィンドウとし、t を返します。そうでない場合は、window のフレームの現在の構成をそのまま維持し、nil を返します。

この関数は、combine-windowsの効果を取り消すのに便利です。例えば、隣接する2つのウィンドウw1とw2の状態を計算するには、次のように操作します。まず、w1とw2を引数としてcombine-windowsを呼び出し、その結果をwに格納します。次に、引数wを指定してwindow-state-getを呼び出します。最後に、wを引数としてuncombine-windowを呼び出し、combine-windowsの呼び出し前に存在していたウィンドウ構成を取得します。