Bevorzugen Sie vertikale Teilungen gegenüber horizontalen


9

Es gibt mehrere ähnliche Fragen. Ich habe sie alle gelesen und sie geben keine Antwort auf mein Szenario. Ich möchte, dass Emacs vertikale Teilungen (Aufteilen von Fenstern in linke und rechte Teile) gegenüber horizontalen Teilen bevorzugen, auch wenn sowohl horizontale als auch vertikale Teilungen möglich sind . Dies ist, was das Handbuch sagt:

Die Aufteilung kann entweder vertikal oder horizontal sein, abhängig von den Variablen Aufteilungshöhenschwelle und Aufteilungsbreitenschwelle. Diese Variablen sollten ganzzahlige Werte haben. Wenn der Schwellenwert für die Teilungshöhe kleiner als die Höhe des ausgewählten Fensters ist, wird durch die Teilung das neue Fenster darunter platziert. Wenn der Schwellenwert für die Teilungsbreite kleiner als die Breite des Fensters ist, wird das neue Fenster durch die Teilung rechts angezeigt.

Wenn also beide split-height-thresholdund split-width-thresholdkleiner als die Breite und Höhe des Fensters sind, führen Emacs eine horizontale Aufteilung durch. Ich will das Gegenteil. Wenn beide Schwellenwerte kleiner sind, führen Sie eine vertikale Aufteilung durch.

Eine Möglichkeit, dies zu erreichen, ist die Einstellung split-height-thresholdauf nil, aber das gefällt mir nicht, weil dadurch die horizontale Aufteilung vollständig deaktiviert wird.

Ich habe mir die split-window-sensiblyFunktion angesehen, bin aber nicht gut genug in elisp, um meine eigene my-split-window-sensiblyFunktion zu schreiben, die so funktioniert, wie ich es möchte.


Es gibt eine Variable namens, split-window-preferred-functiondie so eingestellt werden kann, dass eine benutzerdefinierte Funktion verwendet wird. Schauen Sie sich die Funktion genau an split-window-sensiblyund prüfen Sie, ob sie Ihren Anforderungen entspricht, indem Sie bestimmte Variablen wie in Ihrer Frage erwähnt anpassen. Lesen Sie auch die Dokumentzeichenfolge dieser Funktion ... wenn sie nicht Ihren Anforderungen entsprechen kann, dann Sie können eine andere schreiben oder Hilfe beim Schreiben einer anderen Funktion erhalten ...
Lawlist

Antworten:


5

Nach meiner Erfahrung ist dies ein schwierigeres Problem, als man denken könnte, da es nicht immer einfach ist, eine intuitive Vorstellung davon, was sinnvoll ist, genau zu formulieren. Ich werde nur beschreiben, was ich am Ende habe, aber Sie müssen vielleicht herumspielen.

Erstens: Die vorhandene split-window-sensiblyFunktion zieht es immer vor, einen horizontalen Stapel von Fenstern (der verwirrenderweise eine vertikale "Teilung" nennt, obwohl die Teilung horizontal ist ...) über eine nebeneinander angeordnete Anordnung zu erhalten. Es ist einfach genug, eine Funktion mit der entgegengesetzten Präferenz zu erstellen, die im Wesentlichen nur eine Kopie split-window-sensiblymit umgekehrten Präferenzen ist:

(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))))))))

Jetzt haben wir zwei Funktionen: das Original, das einen vertikalen Stapel "bevorzugt", und das neue, das einen horizontalen Stapel "bevorzugt".

Als nächstes brauchen wir eine Funktion, die diejenige bevorzugt, die wir lieber verwenden würden.

(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)))))

Sie müssen hier mit den Werten herumspielen, aber die Grundidee ist, dass wir eine vertikale Anordnung bevorzugen, wenn mindestens doppelt so viel Breite wie Höhe vorhanden ist. Sie könnten denken, Sie wollten es überall dort haben, wo das vorhandene Fenster breiter als hoch ist, aber meiner Erfahrung nach ist das nicht richtig und lässt Sie mit viel zu dünnen Fenstern enden.

Schließlich brauchen wir auch ein paar vernünftige Mindestanforderungen. Ich setze eine split-height-thresholdvon 4 (dh ich möchte nicht, wenn es nicht unvermeidlich ist, weniger als 2 Zeilen in einem Fenster zu haben) und eine split-width-thresholdvon 40 (dh ich möchte nicht, wenn es nicht unvermeidlich ist, weniger als 20 Zeichen im Durchmesser haben in einem Fenster) - zumindest denke ich, dass dies das ist, was diese bedeuten.

Dann , eines nur bindet split-window-preferred-functionansplit-window-really-sensibly

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

Eine andere Idee (die Sie vielleicht bevorzugen) wäre, einfach die "Präferenz für Side-by-Side" -Anordnung zu ersetzen und split-width-thresholdauf 80 zu setzen: Dann würden Sie Side-by-Side-Fenster erhalten, wenn Platz für sie vorhanden ist, denke ich.


1
Es klappt! Aber ich musste die split-height/width-thresholdWerte auf ihrem Standard halten, sonst würde die pop-to-bufferFunktion neue Teilungen erstellen, anstatt alte wiederzuverwenden. Ich bevorzuge eine einzelne Aufteilung von rechts nach links und möchte nicht, dass Emacs-Funktionen damit herumspielen.
Björn Lindqvist

1

Sie können mein Paket verwenden el-patch, um die Funktion so zu implementieren split-window-sensibly-prefer-horizontal, dass deutlich wird, was sich gegenüber dem Original geändert hat split-window-sensibly, und Sie können auch feststellen, ob sich die ursprüngliche Definition in einer zukünftigen Emacs-Version ändert:

(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

Ich habe diese Lösung in der Emacs- Mailingliste gefunden und sie wirkt Wunder:

;; 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

Ein großes Lob an Alexander, den ursprünglichen Autor.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.