水平分割より垂直分割を優先する


9

これに似た質問がいくつかあります。私はそれらすべてを読みましたが、私のシナリオに対する答えを提供していません。emacsで、水平分割と垂直分割の両方が可能であっても、水平分割よりも垂直分割(ウィンドウを左部分と右部分に分割)を優先したいと思います。これはマニュアルが言うことです:

分割は、変数split-height-thresholdとsplit-width-thresholdに応じて、垂直または水平にできます。これらの変数には整数値が必要です。split-height-thresholdが選択されたウィンドウの高さよりも小さい場合、分割により新しいウィンドウが下に配置されます。それ以外の場合、split-width-thresholdがウィンドウの幅よりも小さい場合、分割により新しいウィンドウが右側に配置されます。

両方の場合だsplit-height-thresholdsplit-width-threshold、ウィンドウの幅と高さよりも小さい、Emacsは水平分割を実行します。私は反対が欲しいです。両方のしきい値が小さい場合は、垂直分割を実行します。

それを達成するための一つの方法は、セットにあるsplit-height-thresholdnilが、それは完全に水平分割を無効にしますので、私はそれが好きではありません。

私が見てきたsplit-window-sensibly機能が、私は自分の書き込みにelispので良い十分ではありませんよmy-split-window-sensibly、私が欲しいのように働く機能を。


と呼ばれる変数がありsplit-window-preferred-function、カスタム関数を使用するように設定できます。関数split-window-sensiblyをよく見て、質問で述べたように特定の変数を調整することでニーズに合うかどうかを確認し、その関数のdoc-stringも読んでください...ニーズに合わせることができない場合は、あなたは別のものを書いたり、別の関数を書くための助けを得たりすることができます...
法律家

回答:


5

私の経験では、これは人が考えるかもしれないより難しい問題です。何が賢明であるかという直観的な考えは、正確な言葉で表現することが必ずしも容易ではないからです。私が何をしてしまったのかを説明しますが、いじる必要があるかもしれません。

まず、既存のsplit-window-sensibly関数は常に、ウィンドウの水平方向のスタックで終わることを好みます(分割は水平方向ですが、混乱を招き、垂直方向の「分割」と呼ばれます...)。逆の設定を持つ関数を作成するのは簡単です。基本的にsplit-window-sensiblyは、設定が反転された単なるコピーです。

(defun split-window-sensibly-prefer-horizontal (&optional window)
"Based on split-window-sensibly, but designed to prefer a horizontal split,
i.e. windows tiled side-by-side."
  (let ((window (or window (selected-window))))
    (or (and (window-splittable-p window t)
         ;; Split window horizontally
         (with-selected-window window
           (split-window-right)))
    (and (window-splittable-p window)
         ;; Split window vertically
         (with-selected-window window
           (split-window-below)))
    (and
         ;; If WINDOW is the only usable window on its frame (it is
         ;; the only one or, not being the only one, all the other
         ;; ones are dedicated) and is not the minibuffer window, try
         ;; to split it horizontally disregarding the value of
         ;; `split-height-threshold'.
         (let ((frame (window-frame window)))
           (or
            (eq window (frame-root-window frame))
            (catch 'done
              (walk-window-tree (lambda (w)
                                  (unless (or (eq w window)
                                              (window-dedicated-p w))
                                    (throw 'done nil)))
                                frame)
              t)))
     (not (window-minibuffer-p window))
     (let ((split-width-threshold 0))
       (when (window-splittable-p window t)
         (with-selected-window window
               (split-window-right))))))))

したがって、2つの関数があります。垂直スタックを「優先」する元の関数と、水平スタックを「優先」する新しい関数です。

次に、使用したい関数を優先する傾向がある関数が必要です。

(defun split-window-really-sensibly (&optional window)
  (let ((window (or window (selected-window))))
    (if (> (window-total-width window) (* 2 (window-total-height window)))
        (with-selected-window window (split-window-sensibly-prefer-horizontal window))
      (with-selected-window window (split-window-sensibly window)))))

ここで値をいじる必要がありますが、基本的な考え方は、高さの少なくとも2倍の幅がある場合は常に垂直配置を好むということです。既存のウィンドウが高さよりも広い場所ならどこでもそれを望んでいたと思うかもしれませんが、私の経験ではそれは正しくなく、結局は非常に細いウィンドウになってしまいます。

最後に、適切な最小値も必要です。a split-height-thresholdを4(つまり、不可避でない限り、ウィンドウ内の行が2行未満になることを望まない)およびa split-width-thresholdを40(つまり、不可避でない限り、20文字未満にすることは望まない)ウィンドウ内)-少なくとも私はそれがこれらの意味だと思います。

次に、バインドsplit-window-preferred-functionしますsplit-window-really-sensibly

(setq
   split-height-threshold 4
   split-width-threshold 40 
   split-window-preferred-function 'split-window-really-sensibly)

別のアイデア(あなたが好むかもしれません)は、「並べて表示するための設定」を置き換えsplit-width-thresholdて80に設定することです。そうすれば、スペースがあるときはいつでもウィンドウを並べて表示できます。


1
できます!しかし、split-height/width-threshold値をデフォルトのままにしておかないと、pop-to-buffer古い分割を再利用するのではなく、関数が新しい分割を作成します。私は単一の右/左スプリットを持つことを好み、emacs関数がそれを台無しにしたくありません。
ビョルンLindqvist

1

私のパッケージel-patchを使用してsplit-window-sensibly-prefer-horizontal、元のからの変更点を明確にする方法で関数を実装split-window-sensiblyできます。また、将来のEmacsリリースで元の定義が変更されたかどうかを検出できます。

(el-patch-defun (el-patch-swap
                  split-window-sensibly
                  split-window-sensibly-prefer-horizontal)
  (&optional window)
  "Split WINDOW in a way suitable for `display-buffer'.
WINDOW defaults to the currently selected window.
If `split-height-threshold' specifies an integer, WINDOW is at
least `split-height-threshold' lines tall and can be split
vertically, split WINDOW into two windows one above the other and
return the lower window.  Otherwise, if `split-width-threshold'
specifies an integer, WINDOW is at least `split-width-threshold'
columns wide and can be split horizontally, split WINDOW into two
windows side by side and return the window on the right.  If this
can't be done either and WINDOW is the only window on its frame,
try to split WINDOW vertically disregarding any value specified
by `split-height-threshold'.  If that succeeds, return the lower
window.  Return nil otherwise.

By default `display-buffer' routines call this function to split
the largest or least recently used window.  To change the default
customize the option `split-window-preferred-function'.

You can enforce this function to not split WINDOW horizontally,
by setting (or binding) the variable `split-width-threshold' to
nil.  If, in addition, you set `split-height-threshold' to zero,
chances increase that this function does split WINDOW vertically.

In order to not split WINDOW vertically, set (or bind) the
variable `split-height-threshold' to nil.  Additionally, you can
set `split-width-threshold' to zero to make a horizontal split
more likely to occur.

Have a look at the function `window-splittable-p' if you want to
know how `split-window-sensibly' determines whether WINDOW can be
split."
  (let ((window (or window (selected-window))))
    (or (el-patch-let
            (($fst (and (window-splittable-p window)
                        ;; Split window vertically.
                        (with-selected-window window
                          (split-window-below))))
             ($snd (and (window-splittable-p window t)
                        ;; Split window horizontally.
                        (with-selected-window window
                          (split-window-right)))))
          (el-patch-swap $fst $snd)
          (el-patch-swap $snd $fst))
        (and
         ;; If WINDOW is the only usable window on its frame (it
         ;; is the only one or, not being the only one, all the
         ;; other ones are dedicated) and is not the minibuffer
         ;; window, try to split it s/vertically/horizontally
         ;; disregarding the value of `split-height-threshold'.
         (let ((frame (window-frame window)))
           (or
            (eq window (frame-root-window frame))
            (catch 'done
              (walk-window-tree (lambda (w)
                                  (unless (or (eq w window)
                                              (window-dedicated-p w))
                                    (throw 'done nil)))
                                frame)
              t)))
         (not (window-minibuffer-p window))
         (let (((el-patch-swap split-height-threshold
                               split-width-threshold)
                0))
           (when (window-splittable-p window)
             (with-selected-window window
               ((el-patch-swap split-window-below split-window-right)))))))))

1

私はこの解決策をEmacs メーリングリストで見つけました。

;; Fix annoying vertical window splitting.
;; https://lists.gnu.org/archive/html/help-gnu-emacs/2015-08/msg00339.html
(with-eval-after-load "window"
  (defcustom split-window-below nil
    "If non-nil, vertical splits produce new windows below."
    :group 'windows
    :type 'boolean)

  (defcustom split-window-right nil
    "If non-nil, horizontal splits produce new windows to the right."
    :group 'windows
    :type 'boolean)

  (fmakunbound #'split-window-sensibly)

  (defun split-window-sensibly
      (&optional window)
    (setq window (or window (selected-window)))
    (or (and (window-splittable-p window t)
             ;; Split window horizontally.
             (split-window window nil (if split-window-right 'left  'right)))
        (and (window-splittable-p window)
             ;; Split window vertically.
             (split-window window nil (if split-window-below 'above 'below)))
        (and (eq window (frame-root-window (window-frame window)))
             (not (window-minibuffer-p window))
             ;; If WINDOW is the only window on its frame and is not the
             ;; minibuffer window, try to split it horizontally disregarding the
             ;; value of `split-width-threshold'.
             (let ((split-width-threshold 0))
               (when (window-splittable-p window t)
                 (split-window window nil (if split-window-right
                                              'left
                                            'right))))))))

(setq-default split-height-threshold  4
              split-width-threshold   160) ; the reasonable limit for horizontal splits

元の作者であるアレクサンダーへの称賛。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.